blob: 695be46bf19d39f2ae8b5de07a9af4d4aad4646f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2012 Obeo.
* All rights reserved. This program and the accompanying materials
* are 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.acceleo.model.mtl.resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.eclipse.acceleo.common.AcceleoCommonPlugin;
import org.eclipse.acceleo.common.IAcceleoConstants;
import org.eclipse.core.runtime.content.IContentDescriber;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ContentHandler;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Factory;
import org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl;
/**
* The Acceleo resource factory registry ensure the support for xmi/binary resources in stand alone.
*
* @author <a href="mailto:stephane.begaudeau@obeo.fr">Stephane Begaudeau</a>
* @since 3.1
*/
public class AcceleoResourceFactoryRegistry extends ResourceFactoryRegistryImpl {
/**
* The delegate.
*/
private Resource.Factory.Registry delegate;
/**
* The constructor.
*/
public AcceleoResourceFactoryRegistry() {
delegate = new ResourceFactoryRegistryImpl();
// We initialize our available informations with the values from the global registry.
this.contentTypeIdentifierToFactoryMap.putAll(Resource.Factory.Registry.INSTANCE
.getContentTypeToFactoryMap());
this.extensionToFactoryMap.putAll(Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap());
this.protocolToFactoryMap.putAll(Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap());
}
/**
* The constructor.
*
* @param delegate
* The resource factory registry to which we will delegate most of the operations.
*/
public AcceleoResourceFactoryRegistry(Resource.Factory.Registry delegate) {
this.delegate = delegate;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl#getFactory(org.eclipse.emf.common.util.URI)
*/
@Override
public Factory getFactory(URI uri) {
Factory factory = delegatedGetFactory(uri, null);
if (factory != null) {
return factory;
}
return delegate.getFactory(uri);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl#getFactory(org.eclipse.emf.common.util.URI,
* java.lang.String)
*/
@Override
public Factory getFactory(URI uri, String contentType) {
Factory factory = delegatedGetFactory(uri, contentType);
if (factory != null) {
return factory;
}
return delegate.getFactory(uri, contentType);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl#getProtocolToFactoryMap()
*/
@Override
public Map<String, Object> getProtocolToFactoryMap() {
if (!this.protocolToFactoryMap.isEmpty()) {
return this.protocolToFactoryMap;
}
return delegate.getProtocolToFactoryMap();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl#getExtensionToFactoryMap()
*/
@Override
public Map<String, Object> getExtensionToFactoryMap() {
if (!this.extensionToFactoryMap.isEmpty()) {
return this.extensionToFactoryMap;
}
return delegate.getExtensionToFactoryMap();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl#getContentTypeToFactoryMap()
*/
@Override
public Map<String, Object> getContentTypeToFactoryMap() {
if (!this.contentTypeIdentifierToFactoryMap.isEmpty()) {
return this.contentTypeIdentifierToFactoryMap;
}
return delegate.getContentTypeToFactoryMap();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceFactoryRegistryImpl#delegatedGetFactory(org.eclipse.emf.common.util.URI,
* java.lang.String)
*/
@Override
protected Factory delegatedGetFactory(URI uri, String contentTypeIdentifier) {
Factory factory = computeFactory(uri, contentTypeIdentifier);
// If we didn't succeed in loading one of Acceleo factories, we will delegate the problem back to EMF
if (factory == null) {
factory = super.delegatedGetFactory(uri, contentTypeIdentifier);
}
return factory;
}
/**
* Computes the factory for the given uri and content type identifier.
*
* @param uri
* The uri
* @param contentTypeIdentifier
* The content type identifier
* @return The factory for the given uri and content type identifier
*/
private Factory computeFactory(URI uri, String contentTypeIdentifier) {
Factory factory = null;
// Not an emtl file ? let EMF handle it
if (!IAcceleoConstants.EMTL_FILE_EXTENSION.equals(uri.fileExtension())) {
return factory;
}
// Unknown content and uri of an emtl file.
String path = uri.toFileString();
if (path == null) {
path = uri.toString();
if (path.startsWith("file:")) { //$NON-NLS-1$
path = path.substring("file:".length()); //$NON-NLS-1$
}
}
if (path != null) {
path = URI.decode(path);
InputStream stream = null;
InputStream containingStream = null;
try {
String jarPrefix = "jar:file:/"; //$NON-NLS-1$
String os = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
if (os.indexOf("win") == -1) { //$NON-NLS-1$
// We are not on windows, let's assume that we are on a unix based system
jarPrefix = "jar:file:"; //$NON-NLS-1$
}
String jarSeparator = "!/"; //$NON-NLS-1$
if (path.startsWith(jarPrefix) && path.contains(jarSeparator)) {
String jarPath = path.substring(jarPrefix.length(), path.indexOf(jarSeparator));
try {
JarFile jar = new JarFile(jarPath);
ZipEntry entry = jar.getEntry(path.substring(path.indexOf(jarSeparator)
+ jarSeparator.length()));
if (entry != null) {
stream = jar.getInputStream(entry);
}
} catch (IOException e) {
// do not log, the jar does not exists
}
} else {
File file = new File(path);
if (file.exists()) {
stream = new FileInputStream(file);
}
}
if ((contentTypeIdentifier == null || ContentHandler.UNSPECIFIED_CONTENT_TYPE
.equals(contentTypeIdentifier))
&& stream != null) {
final int bufferSize = 1024;
containingStream = new LazyInputStream(stream, bufferSize);
EMtlBinaryResourceContentDescriber binaryContentDescriber = new EMtlBinaryResourceContentDescriber();
int describe = binaryContentDescriber.describe(containingStream, null);
if (describe == IContentDescriber.VALID) {
factory = new EMtlBinaryResourceFactoryImpl();
} else {
factory = new EMtlResourceFactoryImpl();
}
}
} catch (FileNotFoundException e) {
AcceleoCommonPlugin.log(e, false);
} catch (IOException e) {
AcceleoCommonPlugin.log(e, false);
} finally {
try {
if (containingStream != null) {
containingStream.close();
}
} catch (IOException e) {
AcceleoCommonPlugin.log(e, false);
}
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
AcceleoCommonPlugin.log(e, false);
}
}
}
if (factory == null) {
if (IAcceleoConstants.BINARY_CONTENT_TYPE.equals(contentTypeIdentifier)) {
factory = new EMtlBinaryResourceFactoryImpl();
} else if (IAcceleoConstants.XMI_CONTENT_TYPE.equals(contentTypeIdentifier)) {
factory = new EMtlResourceFactoryImpl();
}
}
return factory;
}
}