/*
* 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.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.apache.aries.util.filesystem.IDirectory;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.CoordinationException;
import org.osgi.service.subsystem.Subsystem.State;
import org.osgi.service.subsystem.SubsystemException;
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;
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() {
// Doesn't appear to be any need of protecting against re-entry in the
// case of installation.
BasicSubsystem result = null;
// Acquire the global write lock to prevent all other operations until
// the installation is complete. There is no need to hold any other locks.
Activator.getInstance().getLockingStrategy().writeLock();
try {
State state = parent.getState();
if (State.INSTALLING.equals(state)) {
throw new SubsystemException("A child subsystem may not be installed while the parent is in the INSTALLING state");
}
// 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);
try {
TargetRegion region = new TargetRegion(parent);
SubsystemResource ssr = new SubsystemResource(location, content, parent, coordination);
result = Activator.getInstance().getSubsystems().getSubsystemByLocation(location);
if (result != null) {
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);
}
else {
result = (BasicSubsystem)region.find(
ssr.getSubsystemManifest().getSubsystemSymbolicNameHeader().getSymbolicName(),
ssr.getSubsystemManifest().getSubsystemVersionHeader().getVersion());
if (result != null) {
if (!result.getType().equals(ssr.getSubsystemManifest().getSubsystemTypeHeader().getType()))
throw new SubsystemException("Subsystem already exists in target region but has a different type: " + location);
}
else {
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 {
// Release the global write lock.
Activator.getInstance().getLockingStrategy().writeUnlock();
}
return result;
}
private void checkLifecyclePermission(final BasicSubsystem subsystem) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
SecurityManager.checkLifecyclePermission(subsystem);
return null;
}
},
context);
}
}