blob: 544d16eafd0a4a1b950bf20dd48b47f8fe1eca2e [file] [log] [blame]
/*
* 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.apache.aries.subsystem.core.internal;
import java.io.InputStream;
import java.io.IOException;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.apache.aries.util.filesystem.ICloseableDirectory;
import org.apache.aries.util.filesystem.IDirectory;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.CoordinationException;
import org.osgi.service.subsystem.SubsystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InstallAction implements PrivilegedAction<BasicSubsystem> {
private final IDirectory content;
private final AccessControlContext context;
private final InputStream deploymentManifest;
private final String location;
private final BasicSubsystem parent;
private static final Logger logger = LoggerFactory.getLogger(InstallAction.class);
public InstallAction(String location, IDirectory content, BasicSubsystem parent, AccessControlContext context, InputStream deploymentManifest) {
this.location = location;
this.content = content;
this.parent = parent;
this.context = context;
this.deploymentManifest = deploymentManifest;
}
@Override
public BasicSubsystem run() {
// Initialization of a null coordination must be privileged and,
// therefore, occur in the run() method rather than in the constructor.
Coordination coordination = Utils.createCoordination(parent);
BasicSubsystem result = null;
try {
TargetRegion region = new TargetRegion(parent);
SubsystemResource ssr = new SubsystemResource(location, content, parent);
result = Activator.getInstance().getSubsystems().getSubsystemByLocation(location);
if (result != null) {
checkLifecyclePermission(result);
if (!region.contains(result))
throw new SubsystemException("Location already exists but existing subsystem is not part of target region: " + location);
if (!(result.getSymbolicName().equals(ssr.getSubsystemManifest().getSubsystemSymbolicNameHeader().getSymbolicName())
&& result.getVersion().equals(ssr.getSubsystemManifest().getSubsystemVersionHeader().getVersion())
&& result.getType().equals(ssr.getSubsystemManifest().getSubsystemTypeHeader().getType())))
throw new SubsystemException("Location already exists but symbolic name, version, and type are not the same: " + location);
return (BasicSubsystem)ResourceInstaller.newInstance(coordination, result, parent).install();
}
result = (BasicSubsystem)region.find(
ssr.getSubsystemManifest().getSubsystemSymbolicNameHeader().getSymbolicName(),
ssr.getSubsystemManifest().getSubsystemVersionHeader().getVersion());
if (result != null) {
checkLifecyclePermission(result);
if (!result.getType().equals(ssr.getSubsystemManifest().getSubsystemTypeHeader().getType()))
throw new SubsystemException("Subsystem already exists in target region but has a different type: " + location);
return (BasicSubsystem)ResourceInstaller.newInstance(coordination, result, parent).install();
}
result = new BasicSubsystem(ssr, deploymentManifest);
checkLifecyclePermission(result);
return (BasicSubsystem)ResourceInstaller.newInstance(coordination, result, parent).install();
}
catch (Throwable t) {
coordination.fail(t);
}
finally {
try {
coordination.end();
}
catch (CoordinationException e) {
Throwable t = e.getCause();
if (t instanceof SubsystemException)
throw (SubsystemException)t;
if (t instanceof SecurityException)
throw (SecurityException)t;
throw new SubsystemException(t);
}
finally {
closeContentIfIClosable();
}
}
return result;
}
private void closeContentIfIClosable() {
//clean up temp file
if (content instanceof ICloseableDirectory) {
try{
((ICloseableDirectory) content).close();
}
catch (IOException ioex) {
logger.info("Exception calling close for content {}. Exception {}",
content, ioex);
}
}
}
private void checkLifecyclePermission(final BasicSubsystem subsystem) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
SecurityManager.checkLifecyclePermission(subsystem);
return null;
}
},
context);
}
}