/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.core.runtime.internal;
import com.bc.ceres.core.CoreException;
import com.bc.ceres.core.ProgressMonitor;
import com.bc.ceres.core.runtime.Activator;
import com.bc.ceres.core.runtime.Dependency;
import com.bc.ceres.core.runtime.Extension;
import com.bc.ceres.core.runtime.ExtensionPoint;
import com.bc.ceres.core.runtime.Module;
import com.bc.ceres.core.runtime.ModuleContext;
import com.bc.ceres.core.runtime.ModuleState;
import com.bc.ceres.core.runtime.Version;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* The {@link Module} default implementation.
* Instances of this class can only be created via the {@link ModuleManifestParser}.
*/
public class ModuleImpl implements Module {
public static final ModuleImpl[] EMPTY_ARRAY = new ModuleImpl[0];
// The following are all initialised by the ModuleManifestParser
private String manifestVersion;
private String symbolicName;
private String name;
private Version version;
private String description;
private String packaging;
private String activatorClassName;
private String categoriesString; // IDE warning "private field never assigned" is ok
private String changelog; // IDE warning "private field never used" is ok
private String copyright; // IDE warning "private field never used" is ok
private String vendor; // IDE warning "private field never used" is ok
private String contactAddress; // IDE warning "private field never used" is ok
private String funding; // IDE warning "private field never used" is ok
private String url; // IDE warning "private field never used" is ok
private boolean usingJni; // IDE warning "private field never assigned" is ok
private String aboutUrl;
private String licenseUrl;
private ArrayList<DependencyImpl> declaredDependencies; // IDE warning "private field never assigned" is ok
private ArrayList<ExtensionPointImpl> extensionPoints; // IDE warning "private field never assigned" is ok
private ArrayList<ExtensionImpl> extensions; // IDE warning "private field never assigned" is ok
// The following are initialised by the framework
private transient String[] categories;
private transient RuntimeImpl runtime; // initialised by RuntimeImpl
private transient long moduleId; // initialised by RuntimeImpl
private transient ModuleState state; // set by various components
private transient ModuleRegistry registry; // initialised by ModuleRegistry of RuntimeImpl
// The following are initialised by the ModuleReader
private transient URL location;
private transient String[] impliciteLibs;
private transient String[] impliciteNativeLibs;
private transient long contentLength;
private transient long lastModified;
// The following are initialised by the ModuleResolver
private transient String[] declaredLibs;
private transient URL[] libDependencies;
private transient ModuleImpl[] moduleDependencies;
private transient ClassLoader classLoader;
private List<ResolveException> resolveWarnings;
private List<ResolveException> resolveErrors;
private transient int refCount;
private transient Activator activator; // initialised by ModuleStarter
private transient ModuleContext context; // initialised by ModuleStarter
// avoid direct instantiation, modules can only be instantiated by the ModuleManfestParser
private ModuleImpl() {
}
public String getManifestVersion() {
return manifestVersion;
}
public long getModuleId() {
return moduleId;
}
public String getSymbolicName() {
return symbolicName;
}
public Version getVersion() {
return version;
}
public ModuleState getState() {
return state;
}
public String getName() {
return name;
}
public String getVendor() {
return vendor;
}
public String getChangelog() {
return changelog;
}
public String getCopyright() {
return copyright;
}
public String getContactAddress() {
return contactAddress;
}
public String getFunding() {
return funding == null ? "" : funding;
}
public String getUrl() {
return url;
}
public String getDescription() {
return description;
}
public String[] getCategories() {
return categories;
}
public String getActivatorClassName() {
return activatorClassName;
}
public String getPackaging() {
return packaging;
}
public URL getLocation() {
return location;
}
public boolean isNative() {
return usingJni;
}
public String getAboutUrl() {
return aboutUrl;
}
public long getContentLength() {
return contentLength;
}
public long getLastModified() {
return lastModified;
}
public String getLicenseUrl() {
return licenseUrl;
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
checkClassLoader();
return getClassLoader().loadClass(name);
}
public URL getResource(String name) {
checkClassLoader();
return getClassLoader().getResource(name);
}
public InputStream getResourceAsStream(String name) {
checkClassLoader();
return getClassLoader().getResourceAsStream(name);
}
public Enumeration<URL> getResources(String name) throws IOException {
checkClassLoader();
return getClassLoader().getResources(name);
}
// Introduce not before usage of JRE 1.6 is agreed.
/*
public <S> ServiceLoader<S> getServices(Class<S> service) {
checkClassLoader();
return ServiceLoader.load(service, getClassLoader());
}
*/
public Dependency[] getDeclaredDependencies() {
return declaredDependencies != null ? declaredDependencies.toArray(
new DependencyImpl[declaredDependencies.size()]) : DependencyImpl.EMPTY_ARRAY;
}
public ExtensionPoint[] getExtensionPoints() {
return extensionPoints != null ? extensionPoints.toArray(
new ExtensionPointImpl[extensionPoints.size()]) : ExtensionPointImpl.EMPTY_ARRAY;
}
public Extension[] getExtensions() {
return extensions != null ? extensions.toArray(
new ExtensionImpl[extensions.size()]) : ExtensionImpl.EMPTY_ARRAY;
}
public ExtensionPoint getExtensionPoint(String extensionPointId) {
if (extensionPoints == null) {
return null;
}
for (ExtensionPointImpl extensionPoint : extensionPoints) {
if (extensionPoint.getId().equals(extensionPointId)) {
return extensionPoint;
}
}
return registry.getExtensionPoint(extensionPointId);
}
public Extension getExtension(String extensionId) {
if (extensions == null) {
return null;
}
for (Extension extension : extensions) {
if (extensionId.equals(extension.getId())) {
return extension;
}
}
return null;
}
@Override
public int hashCode() {
return symbolicName.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj == this;
}
@Override
public String toString() {
return getClass().getName() + "[moduleId=" + moduleId + ", symbolicName=" + symbolicName + ", version=" + version + "]";
}
public void uninstall(ProgressMonitor pm) throws CoreException {
ModuleUninstaller moduleUninstaller = new ModuleUninstaller(runtime.getLogger());
try {
moduleUninstaller.uninstallModule(this);
} catch (IOException e) {
throw new CoreException(e);
}
}
// end of public API
/////////////////////////////////////////////////////////////////////////
String getCategoriesString() {
return categoriesString;
}
public void setManifestVersion(String manifestVersion) {
this.manifestVersion = manifestVersion;
}
void setCategories(String[] categories) {
this.categories = categories;
}
void setModuleId(long moduleId) {
checkRegistered();
this.moduleId = moduleId;
}
public void setSymbolicName(String symbolicName) {
this.symbolicName = symbolicName;
}
void setName(String name) {
this.name = name;
}
/*internal*/
public void setVersion(Version version) {
this.version = version;
}
void setDescription(String description) {
this.description = description;
}
public void setAboutUrl(String aboutUrl) {
this.aboutUrl = aboutUrl;
}
public void setLicenseUrl(String licenseUrl) {
this.licenseUrl = licenseUrl;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
void setActivatorClassName(String activatorClassName) {
this.activatorClassName = activatorClassName;
}
void setPackaging(String packaging) {
this.packaging = packaging;
}
void setRefCount(int refCount) {
this.refCount = refCount;
}
void initDeclaredComponents() {
if (declaredDependencies != null) {
for (DependencyImpl dependency : declaredDependencies) {
dependency.setDeclaringModule(this);
}
}
if (extensionPoints != null) {
for (ExtensionPointImpl extensionPoint : extensionPoints) {
extensionPoint.setDeclaringModule(this);
}
}
if (extensions != null) {
for (ExtensionImpl extension : extensions) {
extension.setDeclaringModule(this);
}
}
}
ModuleRegistry getRegistry() {
return registry;
}
void setRegistry(ModuleRegistry registry) {
checkRegistered();
this.registry = registry;
}
public void setLocation(URL location) {
checkRegistered();
this.location = location;
}
String[] getImpliciteLibs() {
return impliciteLibs;
}
void setImpliciteLibs(String[] impliciteLibs) {
this.impliciteLibs = impliciteLibs;
}
String[] getImpliciteNativeLibs() {
return impliciteNativeLibs;
}
void setImpliciteNativeLibs(String[] impliciteNativeLibs) {
this.impliciteNativeLibs = impliciteNativeLibs;
}
String[] getDeclaredLibs() {
return declaredLibs;
}
void setDeclaredLibs(String[] declaredLibs) {
this.declaredLibs = declaredLibs;
}
URL[] getLibDependencies() {
return libDependencies;
}
void setLibDependencies(URL[] libDependencies) {
this.libDependencies = libDependencies;
}
ModuleImpl[] getModuleDependencies() {
return moduleDependencies;
}
void setModuleDependencies(ModuleImpl[] moduleDependencies) {
this.moduleDependencies = moduleDependencies;
}
/*internal*/
public void setState(ModuleState state) {
this.state = state;
}
public ClassLoader getClassLoader() {
return classLoader;
}
void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
Activator getActivator() {
return activator;
}
void setActivator(Activator activator) {
this.activator = activator;
}
ModuleContext getContext() {
return context;
}
void setContext(ModuleContext context) {
this.context = context;
}
int getRefCount() {
return refCount;
}
void incrementRefCount() {
refCount++;
}
RuntimeImpl getRuntime() {
return runtime;
}
void setRuntime(RuntimeImpl runtime) {
this.runtime = runtime;
}
void start() throws CoreException {
new ModuleStarter(this).run();
}
void stop() throws CoreException {
new ModuleStopper(this).run();
}
private void checkClassLoader() {
if (classLoader == null) {
throw new IllegalStateException("classLoader == null");
}
}
private void checkRegistered() {
if (registry != null) {
throw new IllegalStateException("illegal operation, module already registered");
}
}
boolean hasResolveErrors() {
return hasResolveExceptions(resolveErrors);
}
ResolveException[] getResolveErrors() {
return getResolveExceptions(resolveErrors);
}
void addResolveError(ResolveException resolveException) {
resolveErrors = addResolveException(resolveException, resolveErrors);
}
ResolveException[] getResolveWarnings() {
return getResolveExceptions(resolveWarnings);
}
void addResolveWarning(ResolveException resolveException) {
resolveWarnings = addResolveException(resolveException, resolveWarnings);
}
private boolean hasResolveExceptions(List<ResolveException> resolveExceptions) {
return resolveExceptions != null && !resolveExceptions.isEmpty();
}
private ResolveException[] getResolveExceptions(List<ResolveException> resolveExceptionList) {
if (resolveExceptionList == null) {
return new ResolveException[0];
}
return resolveExceptionList.toArray(new ResolveException[resolveExceptionList.size()]);
}
private List<ResolveException> addResolveException(ResolveException resolveException,
List<ResolveException> resolveExceptionList) {
if (resolveExceptionList == null) {
resolveExceptionList = new ArrayList<ResolveException>(3);
}
int n = resolveExceptionList.size();
if (n > 0) {
String message = resolveException.getMessage();
String lastMessage = resolveExceptionList.get(n - 1).getMessage();
if (lastMessage != null && lastMessage.equals(message)) {
return resolveExceptionList;
}
}
resolveExceptionList.add(resolveException);
return resolveExceptionList;
}
@Override
public int compareTo(Module o) {
return this.getName().compareTo(o.getName());
}
}