Java tutorial
/* * Copyright 2004-2014 the Seasar Foundation and the Others. * * Licensed 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.seasar.uruma.eclipath.classpath; import static org.seasar.uruma.eclipath.Constants.*; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.seasar.uruma.eclipath.Logger; import org.seasar.uruma.eclipath.exception.PluginRuntimeException; import org.seasar.uruma.eclipath.model.ClasspathKind; import org.seasar.uruma.eclipath.util.AssertionUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; /** * The class dealing with the Eclipse .classpath file. * * @author y-komori */ public class EclipseClasspath { private static final String DOT_CLASSPATH_FILENAME = ".classpath"; public static final String ELEMENT_CLASSPATH = "classpath"; public static final String ELEMENT_CLASSPATHENTRY = "classpathentry"; public static final String ELEMENT_ATTRIBUTES = "attributes"; public static final String ELEMENT_ATTRIBUTE = "attribute"; public static final String ATTR_KIND = "kind"; public static final String ATTR_SOURCEPATH = "sourcepath"; public static final String ATTR_VALUE = "value"; public static final String ATTR_NAME = "name"; public static final String ATTR_PATH = "path"; public static final String ATTRNAME_JAVADOC_LOCATION = "javadoc_location"; public static final String KIND_LIB = ClasspathKind.LIB.toString(); public static final String KIND_VAR = ClasspathKind.VAR.toString(); public static final String KIND_CON = ClasspathKind.CON.toString(); public static final String CLASSPATH_JRE_CONTAINER_PREFIX = "org.eclipse.jdt.launching.JRE_CONTAINER/" + "org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"; protected File classpathFile; protected Document document; protected Element classpathElement; protected boolean isChanged; /** * Constructs new instance. * * @param projectBaseDir */ public EclipseClasspath(File projectBaseDir) { AssertionUtil.assertNotNull("projectBaseDir", projectBaseDir); String filename = projectBaseDir.getAbsolutePath() + SEP + DOT_CLASSPATH_FILENAME; classpathFile = new File(filename); } public Document load() { if (classpathFile.exists()) { isChanged = false; return loadDotClassPath(classpathFile); } else { isChanged = true; return createEmptyDotClassPath(); } } private Document createEmptyDotClassPath() { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); Document document = builder.newDocument(); classpathElement = document.createElement(ELEMENT_CLASSPATH); document.appendChild(classpathElement); return document; } catch (ParserConfigurationException ex) { throw new PluginRuntimeException(ex); } } private Document loadDotClassPath(File file) { Logger.info("Loading " + file.getAbsolutePath() + " ..."); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); document = builder.parse(file); classpathElement = document.getDocumentElement(); NodeList nodeList = document.getElementsByTagName(ELEMENT_CLASSPATHENTRY); int length = nodeList.getLength(); for (int i = 0; i < length; i++) { Element element = (Element) nodeList.item(i); Logger.debug("ClasspathEntry loaded. path=" + element.getAttribute(ATTR_PATH)); } return document; } catch (Exception ex) { throw new PluginRuntimeException(ex); } } public List<ClasspathEntry> getAllClasspathEntries() { List<ClasspathEntry> result = new ArrayList<ClasspathEntry>(); NodeList childNodes = classpathElement.getChildNodes(); int size = childNodes.getLength(); for (int i = 0; i < size; i++) { Node item = childNodes.item(i); if (item instanceof Element) { Element element = (Element) item; String nodeName = element.getNodeName(); String kind = element.getAttribute(ATTR_KIND); if (ELEMENT_CLASSPATHENTRY.equals(nodeName) && (KIND_LIB.equals(kind) || KIND_VAR.equals(kind))) { ClasspathEntry entry = new ClasspathEntry(element); result.add(entry); } } } return result; } public void addClasspathEntry(ClasspathKind kind, String path, String sourcePath, String javadocPath) { if (kind != ClasspathKind.LIB && kind != ClasspathKind.VAR) { throw new IllegalArgumentException("kind must be 'lib' or 'var'"); } Element entry = document.createElement(ELEMENT_CLASSPATHENTRY); classpathElement.appendChild(entry); entry.setAttribute(ATTR_KIND, kind.toString()); entry.setAttribute(ATTR_PATH, path); if (sourcePath != null) { entry.setAttribute(ATTR_SOURCEPATH, sourcePath); } if (javadocPath != null) { addAttributeElement(entry, ATTRNAME_JAVADOC_LOCATION, javadocPath); } Logger.info("Library added. : " + path); isChanged = true; return; } public void addJavaContainerClasspathEntry(CompilerConfiguration compilerConfiguration) { if (compilerConfiguration.getTargetVersion() == null) { return; } String jre = compilerConfiguration.getJreLibraryName(); String path = CLASSPATH_JRE_CONTAINER_PREFIX + jre; // Check current entry Element existingEntry = findJavaContainerClasspathEntry(); if (existingEntry != null) { if (path.equals(existingEntry.getAttribute(ATTR_PATH))) { // JRE Container is ok, nothing to do. return; } else { existingEntry.setAttribute(ATTR_PATH, path); Logger.info("JRE Container changed. : " + jre); isChanged = true; return; } } else { // Current entry not found Element entry = document.createElement(ELEMENT_CLASSPATHENTRY); classpathElement.appendChild(entry); entry.setAttribute(ATTR_KIND, KIND_CON); entry.setAttribute(ATTR_PATH, path); Logger.info("JRE Container added. : " + jre); isChanged = true; return; } } public Element findJavaContainerClasspathEntry() { NodeList elements = document.getElementsByTagName(ELEMENT_CLASSPATHENTRY); int size = elements.getLength(); for (int i = 0; i < size; i++) { Element element = (Element) (elements.item(i)); if (element.getAttribute(ATTR_PATH).startsWith(CLASSPATH_JRE_CONTAINER_PREFIX)) { return element; } } return null; } /** * Add 'attribute' element to specified parent element. if parent element * has no 'attributes' element, this method automatically creates that * element. * * @param parent * parent element * @param name * attribute element's 'name' attribute * @param value * attribute element's 'value' attribute */ private void addAttributeElement(Element parent, String name, String value) { Element attributeElement = document.createElement(ELEMENT_ATTRIBUTE); attributeElement.setAttribute(ATTR_NAME, name); attributeElement.setAttribute(ATTR_VALUE, value); NodeList attributesList = parent.getElementsByTagName(ELEMENT_ATTRIBUTES); Element attributesElement; if (attributesList.getLength() == 0) { attributesElement = document.createElement(ELEMENT_ATTRIBUTES); parent.appendChild(attributesElement); } else { attributesElement = (Element) attributesList.item(0); } attributesElement.appendChild(attributeElement); isChanged = true; } public Element findClasspathEntry(String path) { NodeList elements = document.getElementsByTagName(ELEMENT_CLASSPATHENTRY); int size = elements.getLength(); for (int i = 0; i < size; i++) { Element element = (Element) (elements.item(i)); if (path.equals(element.getAttribute(ATTR_PATH))) { return element; } } return null; } public List<Element> findClasspathEntry(Pattern pattern) { List<Element> result = new ArrayList<Element>(); NodeList elements = document.getElementsByTagName(ELEMENT_CLASSPATHENTRY); int size = elements.getLength(); for (int i = 0; i < size; i++) { Element element = (Element) (elements.item(i)); String path = element.getAttribute(ATTR_PATH); Matcher matcher = pattern.matcher(path); if (matcher.matches()) { result.add(element); } } return result; } public void removeClasspathEntries(Collection<ClasspathEntry> entries) { for (ClasspathEntry entry : entries) { removeClasspathEntry(entry); } } public void removeClasspathEntry(ClasspathEntry entry) { Element target = findClasspathEntry(entry.getPath()); if (target != null) { removeClasspathEntryElement(target); } } public void removeClasspathEntryElements(Collection<Element> entries) { for (Element entry : entries) { removeClasspathEntryElement(entry); } } public void removeClasspathEntryElement(Element entry) { Node nextSibling = entry.getNextSibling(); Node removed = classpathElement.removeChild(entry); if (removed != null) { if (nextSibling != null && isWhitespaceText(nextSibling)) { classpathElement.removeChild(nextSibling); } Logger.info("Library removed. : " + entry.getAttribute(ATTR_PATH)); isChanged = true; } } public String getPath(Element classpathEntry) { return classpathEntry.getAttribute(ATTR_PATH); } public boolean isWhitespaceText(Node node) { if (node.getNodeType() == Node.TEXT_NODE) { String text = ((Text) node).getData(); return StringUtils.isWhitespace(text); } else { return false; } } public void write() { if (!isChanged) { Logger.info(".classpath is not changed."); return; } BufferedOutputStream os = null; try { os = new BufferedOutputStream(new FileOutputStream(classpathFile)); writeDocument(os); os.flush(); Logger.info(".classpath wrote : " + classpathFile.getAbsolutePath()); } catch (IOException ex) { Logger.error(ex.getLocalizedMessage(), ex); } finally { IOUtils.closeQuietly(os); } } private void writeDocument(OutputStream out) { TransformerFactory factory = TransformerFactory.newInstance(); try { Transformer transformer = factory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); Source source = new DOMSource(document); Result result = new StreamResult(out); transformer.transform(source, result); } catch (Exception ex) { throw new PluginRuntimeException(ex); } } }