/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* 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.osmorc.frameworkintegration.impl;
import com.intellij.openapi.util.io.JarUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.osgi.jps.build.CachingBundleInfoProvider;
import org.osmorc.frameworkintegration.FrameworkInstanceDefinition;
import org.osmorc.frameworkintegration.FrameworkInstanceManager;
import org.osmorc.i18n.OsmorcBundle;
import org.osmorc.run.ui.SelectedBundle;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
/**
* Base class for all {@link FrameworkInstanceManager}s.
*/
public abstract class AbstractFrameworkInstanceManager implements FrameworkInstanceManager {
@Nullable
public String getVersion(@NotNull FrameworkInstanceDefinition instance) {
Collection<SelectedBundle> bundles = getFrameworkBundles(instance, FrameworkBundleType.SYSTEM);
if (bundles.size() == 1) {
String path = bundles.iterator().next().getBundlePath();
if (path != null) {
return CachingBundleInfoProvider.getBundleVersion(path);
}
}
return null;
}
@Nullable
@Override
public String checkValidity(@NotNull FrameworkInstanceDefinition instance) {
String basePath = instance.getBaseFolder();
if (basePath == null || !new File(basePath).isDirectory()) {
return OsmorcBundle.message("framework.directory.missing", (basePath != null ? basePath : ""), instance.getFrameworkIntegratorName());
}
String version = getVersion(instance);
if (version == null) {
return OsmorcBundle.message("framework.jar.missing", basePath, instance.getFrameworkIntegratorName());
}
if (StringUtil.isEmptyOrSpaces(instance.getName())) {
return OsmorcBundle.message("framework.name.missing");
}
return null;
}
@NotNull
protected Collection<SelectedBundle> collectBundles(@NotNull FrameworkInstanceDefinition instance,
@NotNull FrameworkBundleType type,
@NotNull String[] bundleDirs,
@NotNull Pattern sysNamePattern,
@Nullable String sysControlClass,
int sysExpected,
@Nullable Pattern shellNamePattern,
@Nullable String shellControlClass,
int shellExpected) {
String basePath = instance.getBaseFolder();
if (basePath == null || !new File(basePath).isDirectory()) {
return ContainerUtil.emptyList();
}
int expected = type == FrameworkBundleType.SYSTEM ? sysExpected : type == FrameworkBundleType.SHELL ? shellExpected : -1;
if (expected == 0) return ContainerUtil.emptyList();
Collection<SelectedBundle> bundles = ContainerUtil.newArrayList();
outer:
for (File dir : flattenDirPatterns(basePath, bundleDirs)) {
File[] files = ObjectUtils.notNull(dir.listFiles(), ArrayUtil.EMPTY_FILE_ARRAY);
for (File file : files) {
FrameworkBundleType bundleType = detectType(file, sysNamePattern, sysControlClass, shellNamePattern, shellControlClass);
if (bundleType == type) {
SelectedBundle bundle = makeBundle(file);
bundles.add(bundle);
if (expected > 0 && bundles.size() == expected) {
break outer;
}
}
}
}
if (expected > 0 && bundles.size() < expected) {
return Collections.emptyList();
}
return bundles;
}
protected List<File> flattenDirPatterns(String basePath, String[] bundleDirs) {
List<File> dirs = ContainerUtil.newArrayList();
for (String subDir : bundleDirs) {
if (subDir.isEmpty()) {
dirs.add(new File(basePath));
}
else if (subDir.endsWith("/*")) {
File[] nestedDirs = new File(basePath, subDir.substring(0, subDir.length() - 2)).listFiles();
if (nestedDirs != null) {
ContainerUtil.addAll(dirs, nestedDirs);
}
}
else {
dirs.add(new File(basePath, subDir));
}
}
return dirs;
}
protected FrameworkBundleType detectType(File file, Pattern sysPattern, String sysClass, Pattern shellPattern, String shellClass) {
FrameworkBundleType bundleType = null;
String name = file.getName();
if (name.endsWith(".jar") && JarUtil.containsEntry(file, JarFile.MANIFEST_NAME)) {
if (sysPattern.matcher(name).matches() && (sysClass == null || JarUtil.containsClass(file, sysClass))) {
bundleType = FrameworkBundleType.SYSTEM;
}
else if (shellPattern != null && shellPattern.matcher(name).matches() &&
(shellClass == null || JarUtil.containsClass(file, shellClass))) {
bundleType = FrameworkBundleType.SHELL;
}
else if (CachingBundleInfoProvider.isBundle(file.getPath())) {
bundleType = FrameworkBundleType.OTHER;
}
}
return bundleType;
}
protected SelectedBundle makeBundle(File file) {
String path = file.getPath();
String bundleName = CachingBundleInfoProvider.getBundleSymbolicName(path);
if (bundleName != null) {
String bundleVersion = CachingBundleInfoProvider.getBundleVersion(path);
if (bundleVersion != null) {
bundleName += " - " + bundleVersion;
}
}
else {
bundleName = file.getName();
}
return new SelectedBundle(SelectedBundle.BundleType.FrameworkBundle, bundleName, path);
}
}