/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model.ui.resources; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import org.apache.xml.serialize.LineSeparator; import org.apache.xml.serialize.Method; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.osgi.util.NLS; import org.jboss.tools.common.model.ui.ModelUIMessages; import org.jboss.tools.common.model.ui.ModelUIPlugin; import org.jboss.tools.common.xml.XMLUtilities; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * @author AU */ public class ResourceLayoutManager { // public public static final String ROOT_TAG = "Layout"; //$NON-NLS-1$ public static final String RESOURCE_ATTR = "resource"; //$NON-NLS-1$ public static final String LAYOUT_EXT = "l4t"; //$NON-NLS-1$ public static final String LAYOUT_PROPERTY = "layout"; //$NON-NLS-1$ // static private static ResourceLayoutManager instance; // documents hash, key == fullPathToResource, value == document private HashMap<String,Document> hashMap = new HashMap<String,Document>(); // AnotherResourceException class class AnotherResourceException extends Exception { private static final long serialVersionUID = 1L; } private ResourceLayoutManager() {} public static ResourceLayoutManager getDefault() { if (instance==null) instance = new ResourceLayoutManager(); return instance; } // return first element with specify elementTag or create new public Element getLayoutElement(IResource resource, String elementTag) { Element element = null; Document document = getLayoutDocument(resource); if(document == null) return null; NodeList nodeList = document.getElementsByTagName(elementTag); if (nodeList==null || nodeList.getLength()==0 || nodeList.item(0)==null) { // create new element element = document.createElement(elementTag); Node root = document.getFirstChild(); root.appendChild(element); } else { element = (Element)nodeList.item(0); } return element; } private Document getLayoutDocument(IResource resource) { Document document = null; if (resource == null) { ModelUIPlugin.getPluginLog().logError(ModelUIMessages.ResourceLayoutManager_ERROR_RESOURCE_NULL); return null; } String fullResourceLocation = getFullLocation(resource).toString(); String layoutLocation = null; try { if(resource.isAccessible()) { layoutLocation = resource.getPersistentProperty(new QualifiedName("",LAYOUT_PROPERTY)); //$NON-NLS-1$ } } catch (CoreException e) { ModelUIPlugin.getPluginLog().logError(e); } if (layoutLocation == null) layoutLocation = createNewLayoutLocation(resource); //String fullLayoutLocation = getFullLocation(resource).addFileExtension(LAYOUT_EXT).toString(); // try get from hashMap document = (Document)hashMap.get(fullResourceLocation); if (document!=null) return document; // try load from file system try { document = loadDocument(resource); } catch (ParserConfigurationException e) { ModelUIPlugin.getPluginLog().logError(ModelUIMessages.ResourceLayoutManager_ERROR_UNKNOWN_EXCEPTION, e); } catch (SAXException e) { ModelUIPlugin.getPluginLog().logError(ModelUIMessages.ResourceLayoutManager_ERROR_UNKNOWN_EXCEPTION, e); } catch (IOException e) { ModelUIPlugin.getPluginLog().logError(ModelUIMessages.ResourceLayoutManager_ERROR_UNKNOWN_EXCEPTION, e); } catch (AnotherResourceException e) { ModelUIPlugin.getPluginLog().logError(ModelUIMessages.ResourceLayoutManager_ERROR_ANOTHER_HEAD, e); } if (document!=null){ hashMap.put(fullResourceLocation, document); return document; } // try create new document try { document = createNewDocument(resource); } catch (ParserConfigurationException e) { //log(Status.ERROR, ModelUIMessages.getString(ERROR_CREATE_DOCUMENT, new String[] {fullLayoutLocation, fullResourceLocation})); ModelUIPlugin.getPluginLog().logError( NLS.bind(ModelUIMessages.ResourceLayoutManager_ERROR_CREATE_DOCUMENT, layoutLocation, fullResourceLocation)); } if (document!=null){ hashMap.put(fullResourceLocation, document); return document; } return document; } private Document createNewDocument(IResource resource) throws ParserConfigurationException { Document document = null; // try create DocumentBuilder DocumentBuilder builder = null; //DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); builder = DocumentBuilderHolder.getInstance(); // create new document document = builder.newDocument(); createRoot(resource, document); return document; } private Document loadDocument(IResource resource) throws AnotherResourceException, ParserConfigurationException, SAXException, IOException { // String fullResourceLocation = getFullLocation(resource).toString(); String layoutLocation = null; try { if(resource != null && resource.isAccessible()) { layoutLocation = resource.getPersistentProperty(new QualifiedName("",LAYOUT_PROPERTY)); //$NON-NLS-1$ } } catch (CoreException e) { ModelUIPlugin.getPluginLog().logError(e); } if (layoutLocation == null) layoutLocation = createNewLayoutLocation(resource); if(!new File(layoutLocation).isFile()) return null; //String fullLayoutLocation = getFullLocation(resource).addFileExtension(LAYOUT_EXT).toString(); Document document = null; DocumentBuilder builder = null; // try create DocumentBuilder builder = DocumentBuilderHolder.getInstance(); // try parse //document = builder.parse(fullLayoutLocation); document = builder.parse(layoutLocation); // verify head if (document != null) { NodeList nodeList = document.getElementsByTagName(ROOT_TAG); if (nodeList==null || nodeList.getLength()==0 || nodeList.item(0)==null) { // warning //log(ModelUIMessages.getString(WARNING_EMPTY_HEAD, new String[] {fullLayoutLocation})); ModelUIPlugin.getPluginLog().logInfo(NLS.bind(ModelUIMessages.ResourceLayoutManager_WARNING_HEAD_EMPTY, layoutLocation)); // create new head createRoot(resource, document); } /*else { (Element)nodeList.item(0); String fromHead = head.getAttribute(RESOURCE_ATTR); String fromResource = resource.getFullPath().toString(); if (!fromResource.equals(fromHead)) { throw new AnotherResourceException(); } } */ } return document; } private IPath getFullLocation(IResource resource) { IProject project = resource.getProject(); IPath layoutPath = resource.getProjectRelativePath(); IFile layoutFile = project.getFile(layoutPath); return layoutFile.getLocation(); } public void store(IResource resource) { String layoutLocation = null; try { if(resource != null && resource.isAccessible()) { layoutLocation = resource.getPersistentProperty(new QualifiedName("",LAYOUT_PROPERTY)); //$NON-NLS-1$ } } catch (CoreException e) { ModelUIPlugin.getPluginLog().logError(e); } if (layoutLocation==null) { layoutLocation = createNewLayoutLocation(resource); } if (layoutLocation==null) return; File file = new File(layoutLocation); if (!file.exists()) { layoutLocation = createNewLayoutLocation(resource); } String fullResourceLocation = getFullLocation(resource).toString(); //String fullLayoutLocation = getFullLocation(resource).addFileExtension(LAYOUT_EXT).toString(); Document document = (Document)hashMap.get(fullResourceLocation); if (document==null) return; try { //FileWriter writer = new FileWriter(fullLayoutLocation); FileWriter writer = new FileWriter(layoutLocation); XMLSerializer serial = new XMLSerializer(writer, createOutputFormat("UTF-8")); //$NON-NLS-1$ serial.asDOMSerializer(); serial.serialize(document); writer.close(); } catch (IOException e) { //log(Status.ERROR, ModelUIMessages.getString(ERROR_CREATE_DOCUMENT, new String[] {fullLayoutLocation, fullResourceLocation}), e); ModelUIPlugin.getPluginLog().logError(NLS.bind(ModelUIMessages.ResourceLayoutManager_ERROR_CREATE_DOCUMENT, layoutLocation, fullResourceLocation), e); } } private OutputFormat createOutputFormat(String encoding) { if(encoding == null || encoding.length() == 0) encoding = "UTF-8"; //$NON-NLS-1$ OutputFormat format = new OutputFormat(Method.XML, encoding, true); format.setLineSeparator(System.getProperty("line.separator", LineSeparator.Web)); //$NON-NLS-1$ format.setIndent(1); return format; } private Element createRoot(IResource resource, Document document) { Element element = document.createElement(ROOT_TAG); Node oldRoot = document.getFirstChild(); element.setAttribute(RESOURCE_ATTR, resource.getFullPath().toString()); if (oldRoot!=null) { document.removeChild(oldRoot); } document.appendChild(element); return element; } private IPath getPluginMetadataPath() { return Platform.getStateLocation(Platform.getBundle(ModelUIPlugin.PLUGIN_ID)); } private String createNewLayoutLocation(IResource resource) { String fileName = resource.getProject().getName()+"_"+resource.getName()+"_"+System.currentTimeMillis(); //$NON-NLS-1$//$NON-NLS-2$ String layoutLocation = getPluginMetadataPath().toString(); String result = layoutLocation+"/"+fileName+"."+LAYOUT_EXT; //$NON-NLS-1$//$NON-NLS-2$ try { if(resource != null && resource.isAccessible()) { resource.setPersistentProperty(new QualifiedName("", LAYOUT_PROPERTY), result); //$NON-NLS-1$ } } catch (CoreException e) { ModelUIPlugin.getPluginLog().logError(e); } return result; } static class DocumentBuilderHolder { static private DocumentBuilder INSTANCE = XMLUtilities.createDocumentBuilder(); public static DocumentBuilder getInstance() { return INSTANCE; } } }