All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.osgi.internal.location.BasicLocation Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2004, 2022 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Christoph Läubrich - Issue #38 - Expose the url of a location as service properties
 *******************************************************************************/
package org.eclipse.osgi.internal.location;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration.ConfigValues;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.log.EquinoxLogServices;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

/**
 * Internal class.
 */
public class BasicLocation implements Location {
	private static String DEFAULT_LOCK_FILENAME = ".metadata/.lock"; //$NON-NLS-1$

	final private boolean isReadOnly;
	final private URL defaultValue;
	final private String property;
	final private String dataAreaPrefix;
	final private ConfigValues configValues;
	final private AtomicBoolean debug;
	final private EquinoxContainer container;

	private URL location;
	private Location parent;

	// locking related fields
	private File lockFile;
	private Locker locker;

	private ServiceRegistration serviceRegistration;

	public BasicLocation(String property, URL defaultValue, boolean isReadOnly, String dataAreaPrefix, ConfigValues configValues, EquinoxContainer container, AtomicBoolean debug) {
		this.property = property;
		this.defaultValue = defaultValue;
		this.isReadOnly = isReadOnly;
		// make sure the prefix ends with '/' if it is not empty/null
		String tempDataAreaPrefix = dataAreaPrefix == null ? "" : dataAreaPrefix; //$NON-NLS-1$
		tempDataAreaPrefix = tempDataAreaPrefix.replace('\\', '/');
		if (tempDataAreaPrefix.length() > 0 && tempDataAreaPrefix.charAt(tempDataAreaPrefix.length() - 1) != '/') {
			tempDataAreaPrefix += '/';
		}
		this.dataAreaPrefix = tempDataAreaPrefix;
		this.configValues = configValues;
		this.container = container;
		this.debug = debug;
	}

	@Override
	public boolean allowsDefault() {
		return defaultValue != null;
	}

	@Override
	public URL getDefault() {
		return defaultValue;
	}

	@Override
	public synchronized Location getParentLocation() {
		return parent;
	}

	@Override
	public synchronized URL getURL() {
		if (location == null && defaultValue != null) {
			if (debug.get()) {
				EquinoxLogServices logServices = container.getLogServices();
				// Note that logServices can be null if we are very early in the startup.
				if (logServices != null) {
					logServices.log(EquinoxContainer.NAME, FrameworkLogEntry.INFO, "Called Location.getURL() when it has not been set for: \"" + property + "\"", new RuntimeException("Call stack for Location.getURL()")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
				}
			}
			setURL(defaultValue, false);
		}
		return location;
	}

	private synchronized URL getLocation() {
		return location;
	}

	@Override
	public synchronized boolean isSet() {
		return location != null;
	}

	@Override
	public boolean isReadOnly() {
		return isReadOnly;
	}

	/**
	 * @deprecated
	 */
	@Override
	public boolean setURL(URL value, boolean lock) throws IllegalStateException {
		try {
			return set(value, lock);
		} catch (IOException e) {
			return false;
		}
	}

	@Override
	public synchronized boolean set(URL value, boolean lock) throws IllegalStateException, IOException {
		return set(value, lock, null);
	}

	@Override
	public synchronized boolean set(URL value, boolean lock, String lockFilePath) throws IllegalStateException, IOException {
		synchronized (this) {
			if (location != null)
				throw new IllegalStateException(Msg.ECLIPSE_CANNOT_CHANGE_LOCATION);
			File file = null;
			if (value.getProtocol().equalsIgnoreCase("file")) { //$NON-NLS-1$
				try {
					File f = LocationHelper.decodePath(new File(value.getPath()));
					String basePath = f.getCanonicalPath();
					value = LocationHelper.buildURL("file:" + basePath, true); //$NON-NLS-1$
				} catch (IOException e) {
					// do nothing just use the original value
				}
				if (lockFilePath != null && lockFilePath.length() > 0) {
					File givenLockFile = new File(lockFilePath);
					if (givenLockFile.isAbsolute()) {
						file = givenLockFile;
					} else {
						file = new File(value.getPath(), lockFilePath);
					}
				} else {
					file = new File(value.getPath(), DEFAULT_LOCK_FILENAME);
				}
			}
			lock = lock && !isReadOnly;
			if (lock) {
				if (!lock(file, value))
					return false;
			}
			lockFile = file;
			location = value;
			if (property != null) {
				configValues.setConfiguration(property, location.toExternalForm());
			}
		}
		updateUrl(serviceRegistration);
		return true;
	}

	private void updateUrl(ServiceRegistration registration) {
		if (registration != null) {
			Dictionary properties = registration.getReference().getProperties();
			properties.put(Location.SERVICE_PROPERTY_URL, getLocation().toExternalForm());
			try {
				registration.setProperties(properties);
			} catch (IllegalStateException e) {
				// can't update it then...
			}
		}
	}

	public synchronized void setParent(Location value) {
		parent = value;
	}

	@Override
	public synchronized boolean lock() throws IOException {
		if (!isSet())
			throw new IOException(Msg.location_notSet);
		return lock(lockFile, location);
	}

	@Override
	public synchronized boolean isLocked() throws IOException {
		if (!isSet())
			return false;
		return isLocked(lockFile);
	}

	/*
	 * This must be called while holding the synchronization lock for (this)
	 */
	private boolean lock(File lock, URL locationValue) throws IOException {
		if (isReadOnly)
			throw new IOException(NLS.bind(Msg.location_folderReadOnly, lock));
		if (lock == null) {
			if (locationValue != null && !"file".equalsIgnoreCase(locationValue.getProtocol())) //$NON-NLS-1$
				throw new IOException(NLS.bind(Msg.location_notFileProtocol, locationValue));
			throw new IllegalStateException(Msg.location_noLockFile); // this is really unexpected
		}
		if (isLocked())
			return false;
		File parentFile = new File(lock.getParent());
		if (!parentFile.isDirectory()) {
			parentFile.mkdirs();
			if (!parentFile.isDirectory())
				throw new IOException(NLS.bind(Msg.location_folderReadOnly, parentFile));
		}
		setLocker(lock);
		if (locker == null)
			return true;
		boolean locked = false;
		try {
			locked = locker.lock();
			return locked;
		} finally {
			if (!locked)
				locker = null;
		}
	}

	/*
	 * This must be called while holding the synchronization lock for (this)
	 */
	private boolean isLocked(File lock) throws IOException {
		if (lock == null || isReadOnly)
			return true;
		if (!lock.exists())
			return false;
		setLocker(lock);
		return locker.isLocked();
	}

	/*
	 * This must be called while holding the synchronization lock for (this)
	 */
	private void setLocker(File lock) {
		if (locker != null)
			return;
		String lockMode = configValues.getConfiguration(LocationHelper.PROP_OSGI_LOCKING, LocationHelper.LOCKING_NIO);
		locker = LocationHelper.createLocker(lock, lockMode, debug.get());
	}

	@Override
	public synchronized void release() {
		if (locker != null)
			locker.release();
	}

	@Override
	public Location createLocation(Location parentLocation, URL defaultLocation, boolean readonly) {
		BasicLocation result = new BasicLocation(null, defaultLocation, readonly, dataAreaPrefix, configValues, container, debug);
		result.setParent(parentLocation);
		return result;
	}

	@Override
	public URL getDataArea(String filename) throws IOException {
		URL base = getURL();
		if (base == null)
			throw new IOException(Msg.location_notSet);
		String prefix = base.toExternalForm();
		if (prefix.length() > 0 && prefix.charAt(prefix.length() - 1) != '/')
			prefix += '/';
		filename = filename.replace('\\', '/');
		if (filename.length() > 0 && filename.charAt(0) == '/')
			filename = filename.substring(1);
		String spec = prefix + dataAreaPrefix + filename;
		boolean trailingSlash = spec.length() > 0 && spec.charAt(spec.length() - 1) == '/';
		return LocationHelper.buildURL(spec, trailingSlash);
	}

	public void register(BundleContext bundleContext) {
		Dictionary locationProperties = new Hashtable<>(3);
		locationProperties.put(Location.SERVICE_PROPERTY_TYPE, property);
		URL url = getLocation();
		URL defaultUrl = getDefault();
		if (url != null) {
			locationProperties.put(Location.SERVICE_PROPERTY_URL, url.toExternalForm());
		}
		if (defaultUrl != null) {
			locationProperties.put(Location.SERVICE_PROPERTY_DEFAULT_URL, defaultUrl.toExternalForm());
		}
		ServiceRegistration register = bundleContext.registerService(Location.class, this, locationProperties);
		synchronized (this) {
			serviceRegistration = register;
		}
		// just paranoid here... checking if between we have registered and where able
		// to set the serviceRegistration the url has changed...
		if (url != getLocation()) {
			updateUrl(register);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy