| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.modules.projectimport.eclipse.core; |
| |
| import java.io.File; |
| import java.io.FileFilter; |
| import java.io.FileInputStream; |
| import java.io.FilenameFilter; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.logging.Logger; |
| import org.netbeans.modules.projectimport.eclipse.core.spi.LaunchConfiguration; |
| import org.openide.util.Utilities; |
| import org.openide.xml.XMLUtil; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Parses given workspace and fills up it with found data. |
| * |
| * @author mkrauskopf |
| */ |
| final class WorkspaceParser { |
| |
| /** Logger for this class. */ |
| private static final Logger logger = Logger.getLogger(WorkspaceParser.class.getName()); |
| |
| private static final String VM_XML = "org.eclipse.jdt.launching.PREF_VM_XML"; // NOI18N |
| private static final String IGNORED_CP_ENTRY = "##<cp entry ignore>##"; // NOI18N |
| |
| private static final String VARIABLE_PREFIX = "org.eclipse.jdt.core.classpathVariable."; // NOI18N |
| private static final int VARIABLE_PREFIX_LENGTH = VARIABLE_PREFIX.length(); |
| |
| private static final String RESOURCES_VARIABLE_PREFIX = "pathvariable."; // NOI18N |
| private static final int RESOURCES_VARIABLE_PREFIX_LENGTH = RESOURCES_VARIABLE_PREFIX.length(); |
| |
| private static final String USER_LIBRARY_PREFIX = "org.eclipse.jdt.core.userLibrary."; // NOI18N |
| private static final int USER_LIBRARY_PREFIX_LENGTH = USER_LIBRARY_PREFIX.length(); |
| |
| private static final String JSF_LIB_NS = "http://www.eclipse.org/webtools/jsf/schema/jsflibraryregistry.xsd"; // NOI18N |
| |
| private final Workspace workspace; |
| |
| /** Creates a new instance of WorkspaceParser */ |
| WorkspaceParser(Workspace workspace) { |
| this.workspace = workspace; |
| } |
| |
| /** Returns classpath content from project's .classpath file */ |
| void parse() throws ProjectImporterException { |
| try { |
| parseLaunchingPreferences(); |
| parseCorePreferences(); |
| parseResourcesPreferences(); |
| parseWorkspaceProjects(); |
| parseJSFLibraryRegistryV2(); |
| parseLaunchConfigurations(); |
| } catch (IOException e) { |
| throw new ProjectImporterException( |
| "Cannot load workspace properties", e); // NOI18N |
| } |
| } |
| |
| private void parseLaunchingPreferences() throws IOException, ProjectImporterException { |
| if (!workspace.getLaunchingPrefsFile().exists()) { |
| workspace.setJREContainers(new HashMap<String, String>()); |
| return; |
| } |
| for (Map.Entry<String,String> entry : EclipseUtils.loadProperties(workspace.getLaunchingPrefsFile()).entrySet()) { |
| if (entry.getKey().equals(VM_XML)) { |
| Map<String,String> vmMap = PreferredVMParser.parse(entry.getValue()); |
| workspace.setJREContainers(vmMap); |
| } |
| } |
| } |
| |
| private void parseCorePreferences() throws IOException, ProjectImporterException { |
| for (Map.Entry<String,String> entry : EclipseUtils.loadProperties(workspace.getCorePreferenceFile()).entrySet()) { |
| String key = entry.getKey(); |
| String value = entry.getValue(); |
| if (key.startsWith(VARIABLE_PREFIX)) { |
| Workspace.Variable var = new Workspace.Variable(key.substring(VARIABLE_PREFIX_LENGTH), value); |
| workspace.addVariable(var); |
| } else if (key.startsWith(USER_LIBRARY_PREFIX) && !value.startsWith(IGNORED_CP_ENTRY)) { // #73542 |
| String libName = key.substring(USER_LIBRARY_PREFIX_LENGTH); |
| List<String> jars = new ArrayList<String>(); |
| List<String> javadocs = new ArrayList<String>(); |
| List<String> sources = new ArrayList<String>(); |
| UserLibraryParser.getJars(libName, value, jars, javadocs, sources); |
| workspace.addUserLibrary(libName, jars, javadocs, sources); |
| } // else we don't use other properties in the meantime |
| } |
| } |
| |
| /*private*/ void parseJSFLibraryRegistryV2() throws IOException { |
| if (!workspace.getUserJSFLibraries().exists()) { |
| return; |
| } |
| Document xml; |
| try { |
| xml = XMLUtil.parse(new InputSource(Utilities.toURI(workspace.getUserJSFLibraries()).toString()), false, true, XMLUtil.defaultErrorHandler(), null); |
| } catch (SAXException e) { |
| IOException ioe = (IOException) new IOException(workspace.getUserJSFLibraries() + ": " + e.toString()).initCause(e); // NOI18N |
| throw ioe; |
| } |
| |
| Element root = xml.getDocumentElement(); |
| if (!"JSFLibraryRegistry".equals(root.getLocalName()) || // NOI18N |
| !JSF_LIB_NS.equals(root.getNamespaceURI())) { |
| return; |
| } |
| for (Element el : XMLUtil.findSubElements(root)) { |
| String libraryName = el.getAttribute("Name"); // NOI18N |
| List<String> jars = new ArrayList<String>(); |
| for (Element file : XMLUtil.findSubElements(el)) { |
| String path = file.getAttribute("SourceLocation"); // NOI18N |
| if (!"false".equals(file.getAttribute("RelativeToWorkspace"))) { // NOI18N |
| path = new File(workspace.getDirectory(), path).getPath(); |
| } |
| jars.add(path); |
| } |
| // TODO: in Ganymede Javadoc/sources customization does not seem to be persisted. eclipse defect?? |
| workspace.addUserLibrary(libraryName, jars, null, null); |
| } |
| } |
| |
| private void parseResourcesPreferences() throws IOException, ProjectImporterException { |
| if (!workspace.getResourcesPreferenceFile().exists()) { |
| return; |
| } |
| for (Map.Entry<String,String> entry : EclipseUtils.loadProperties(workspace.getResourcesPreferenceFile()).entrySet()) { |
| String key = entry.getKey(); |
| if (key.startsWith(RESOURCES_VARIABLE_PREFIX)) { |
| Workspace.Variable var = new Workspace.Variable(key.substring(RESOURCES_VARIABLE_PREFIX_LENGTH), entry.getValue()); |
| workspace.addResourcesVariable(var); |
| } |
| } |
| } |
| |
| private void parseWorkspaceProjects() throws ProjectImporterException { |
| // directory filter |
| FileFilter dirFilter = new FileFilter() { |
| public boolean accept(File file) { |
| return file.isDirectory(); |
| } |
| }; |
| |
| Set<File> projectsDirs = new HashSet<File>(); |
| // let's find internal projects |
| File[] innerDirs = workspace.getDirectory().listFiles(dirFilter); |
| for (int i = 0; i < innerDirs.length; i++) { |
| File prjDir = innerDirs[i]; |
| if (EclipseUtils.isRegularProject(prjDir)) { |
| // we cannot load projects recursively until we have loaded |
| // information of all projects in the workspace |
| logger.finest("Found a regular Eclipse Project in: " // NOI18N |
| + prjDir.getAbsolutePath()); |
| if (!projectsDirs.contains(prjDir)) { |
| addLightProject(projectsDirs, prjDir, true); |
| } else { |
| logger.finest("Trying to add the same project twice: " // NOI18N |
| + prjDir.getAbsolutePath()); |
| } |
| } // else .metadata or something we don't care about yet |
| } |
| |
| // let's try to find external projects |
| File[] resourceDirs = workspace.getResourceProjectsDir().listFiles(dirFilter); |
| for (int i = 0; i < resourceDirs.length; i++) { |
| File resDir = resourceDirs[i]; |
| File location = getLocation(resDir); |
| if (location != null) { |
| if (EclipseUtils.isRegularProject(location)) { |
| logger.finest("Found a regular Eclipse Project in: " // NOI18N |
| + location.getAbsolutePath()); |
| if (!projectsDirs.contains(location)) { |
| addLightProject(projectsDirs, location, false); |
| } else { |
| logger.finest("Trying to add the same project twice: " // NOI18N |
| + location.getAbsolutePath()); |
| } |
| } else { |
| logger.finest(location.getAbsolutePath() + " does not contain regular project"); // NOI18N |
| } |
| } |
| } |
| |
| // Project instances with base infos are loaded, let's load all the |
| // information we need (we have to do this here because project's |
| // classpath needs at least project's names and abs. paths during |
| // parsing |
| // Load first all .project files to init any links project may have |
| // and then .classpath files. |
| for (EclipseProject project : workspace.getProjects()) { |
| project.setWorkspace(workspace); |
| ProjectFactory.getInstance().loadDotProject(project); |
| } |
| for (EclipseProject project : workspace.getProjects()) { |
| ProjectFactory.getInstance().loadDotClassPath(project); |
| } |
| |
| for (EclipseProject project : workspace.getProjects()) { |
| project.replaceContainers(); |
| } |
| } |
| |
| private void addLightProject(Set<File> projectsDirs, File prjDir, boolean internal) { |
| EclipseProject project = EclipseProject.createProject(prjDir); |
| if (project != null) { |
| project.setName(prjDir.getName()); |
| project.setInternal(internal); |
| workspace.addProject(project); |
| projectsDirs.add(prjDir); |
| } |
| } |
| |
| /** Loads location of external project. */ |
| private static File getLocation(final File prjDir) throws ProjectImporterException { |
| if (".org.eclipse.jdt.core.external.folders".equals(prjDir.getName())) { //NOI18N |
| // ignore this. some internal Eclipse stuff |
| return null; |
| } |
| File locationFile = new File(prjDir, ".location"); // NOI18N |
| if (locationFile.isFile()) { |
| FileInputStream fis = null; |
| try { |
| fis = new FileInputStream(locationFile); |
| return getLocation(fis); |
| } catch (IOException e) { |
| throw new ProjectImporterException("Error during reading " + // NOI18N |
| ".location file", e); // NOI18N |
| } finally { |
| if (fis != null) { |
| try { |
| fis.close(); |
| } catch (IOException e) { |
| throw new ProjectImporterException(e); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Loads location of external project. Package-private for unit tests only. |
| */ |
| static File getLocation(final InputStream is) throws IOException { |
| // starts with 17 bytes. |
| long toSkip = 17; |
| while(toSkip != 0) { |
| toSkip -= is.skip(toSkip); |
| } |
| // follows byte describing path length |
| int pathLength = is.read(); |
| // follows path itself |
| byte[] path = new byte[pathLength]; |
| int read = is.read(path); |
| assert read == pathLength; |
| String pathS = new String(path, StandardCharsets.ISO_8859_1); |
| if (pathS.startsWith("URI//")) { // #89577 // NOI18N |
| pathS = pathS.substring(pathS.indexOf(':') + 1); |
| } |
| if (pathS.length() == 0) { |
| return null; |
| } |
| return new File(pathS); |
| } |
| |
| private void parseLaunchConfigurations() throws IOException, ProjectImporterException { |
| List<LaunchConfiguration> configs = new ArrayList<LaunchConfiguration>(); |
| File[] launches = new File(workspace.getDirectory(), ".metadata/.plugins/org.eclipse.debug.core/.launches").listFiles(new FilenameFilter() { // NOI18N |
| public boolean accept(File dir, String name) { |
| return name.endsWith(".launch"); // NOI18N |
| } |
| }); |
| if (launches != null) { |
| for (File launch : launches) { |
| Document doc; |
| try { |
| doc = XMLUtil.parse(new InputSource(Utilities.toURI(launch).toString()), false, false, null, null); |
| } catch (SAXException x) { |
| throw new ProjectImporterException("Could not parse " + launch, x); |
| } |
| Element launchConfiguration = doc.getDocumentElement(); |
| String type = launchConfiguration.getAttribute("type"); // NOI18N |
| Map<String,String> attrs = new HashMap<String,String>(); |
| NodeList nl = launchConfiguration.getElementsByTagName("stringAttribute"); // NOI18N |
| for (int i = 0; i < nl.getLength(); i++) { |
| Element stringAttribute = (Element) nl.item(i); |
| attrs.put(stringAttribute.getAttribute("key"), stringAttribute.getAttribute("value")); // NOI18N |
| } |
| configs.add(new LaunchConfiguration(launch.getName().replaceFirst("\\.launch$", ""), type, // NOI18N |
| attrs.get("org.eclipse.jdt.launching.PROJECT_ATTR"), // NOI18N |
| attrs.get("org.eclipse.jdt.launching.MAIN_TYPE"), // NOI18N |
| attrs.get("org.eclipse.jdt.launching.PROGRAM_ARGUMENTS"), // NOI18N |
| attrs.get("org.eclipse.jdt.launching.VM_ARGUMENTS"))); // NOI18N |
| } |
| } |
| workspace.setLaunchConfigurations(configs); |
| } |
| |
| } |