/*=============================================================================#
# Copyright (c) 2013-2016 Stephan Wahlbrink (WalWare.de) and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of either (per the licensee's choosing)
# - the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html, or
# - the GNU Lesser General Public License v2.1 or newer
# which accompanies this distribution, and is available at
# http://www.gnu.org/licenses/lgpl.html
#
# Contributors:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.rj.server.srvext;
import static de.walware.rj.server.srvext.ServerUtil.RJ_SERVER_ID;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;
import de.walware.rj.RjInvalidConfigurationException;
public class RJContext {
protected static abstract class PathEntry implements Comparable<PathEntry> {
final String name;
public PathEntry(final String child) {
this.name = child;
}
@Override
public int compareTo(final PathEntry o) {
return this.name.compareTo((o).name);
}
public abstract String getPath();
@Override
public abstract String toString();
}
protected static class FilePathEntry extends PathEntry {
final File dir;
public FilePathEntry(final File dir, final String name) {
super(name);
this.dir = dir;
}
@Override
public String getPath() {
final File file = new File(this.dir, this.name);
if (file.isDirectory()) {
final File binFile = new File(file, "bin");
if (binFile.exists() && binFile.isDirectory()) {
return binFile.getPath();
}
}
return file.getPath();
}
@Override
public String toString() {
return '\'' + this.name + "' in '" + this.dir + '\'';
}
}
private String libPath;
public RJContext(final String libPath) {
this.libPath = libPath;
}
protected RJContext() {
}
public String[] searchRJLibs(final String[] libsIds) throws RjInvalidConfigurationException {
final List<PathEntry> candidates = getRJLibCandidates();
final String[] resolved = new String[libsIds.length];
StringBuilder sb = null;
Collections.sort(candidates);
for (int i = 0; i < libsIds.length; i++) {
final PathEntry entry = searchLib(candidates, libsIds[i]);
if (entry == null) {
if (sb == null) {
sb = new StringBuilder("Missing RJ library ");
}
else {
sb.append(", ");
}
sb.append('\'');
sb.append(libsIds[i]);
sb.append('\'');
}
else {
resolved[i] = entry.getPath();
}
}
if (sb != null) {
sb.append('.');
throw new RjInvalidConfigurationException(sb.toString());
}
return resolved;
}
protected String[] getLibDirPaths() throws RjInvalidConfigurationException {
String path = System.getProperty("de.walware.rj.path");
if (path == null) {
path = this.libPath;
}
if (path == null || path.isEmpty()) {
throw new RjInvalidConfigurationException("Missing or invalid RJ library location.");
}
return path.split(Pattern.quote(File.pathSeparator));
}
protected List<PathEntry> getRJLibCandidates() throws RjInvalidConfigurationException {
final String[] paths = getLibDirPaths();
final List<PathEntry> files = new ArrayList<>(paths.length*10);
for (int i = 0; i < paths.length; i++) {
if (paths[i].length() > 0) {
File dir = new File(paths[i]);
try {
dir = dir.getCanonicalFile();
}
catch (final IOException e) {}
final String[] list = dir.list();
if (list != null) {
for (final String child : list) {
files.add(new FilePathEntry(dir, child));
}
}
}
}
return files;
}
protected PathEntry searchLib(final List<PathEntry> files, final String libId) {
PathEntry found = null;
for (final PathEntry entry : files) {
if (entry.name.startsWith(libId)) {
// without version
if (entry.name.length() == libId.length() // equals
|| (entry.name.length() == libId.length() + 4 && entry.name.endsWith(".jar")) ) {
return entry;
}
// with version suffix
if (entry.name.length() > libId.length()) {
if (entry.name.charAt(libId.length()) == '_') {
found = entry;
}
}
}
}
return found;
}
public String getServerPolicyFilePath() throws RjInvalidConfigurationException {
String serverLib = searchRJLibs(new String[] { RJ_SERVER_ID })[0];
final File libFile = new File(serverLib);
if (libFile.isDirectory()) {
File file = new File(libFile, "localhost.policy");
if (libFile.getName().equals("bin") && !file.exists()) {
file = new File(libFile.getParentFile(), "localhost.policy");
}
return file.toURI().toString();
}
// expect jar file
serverLib = libFile.toURI().toString();
return "jar:" + serverLib + "!/localhost.policy";
}
protected String getPropertiesDirPath() {
return System.getProperty("user.dir");
}
protected InputStream getInputStream(final String path) throws IOException {
final File file = new File(path);
if (!file.exists()) {
return null;
}
return new FileInputStream(file);
}
protected OutputStream getOutputStream(final String path) throws IOException {
final File file = new File(path);
return new FileOutputStream(file, false);
}
public Properties loadProperties(final String name) throws IOException {
if (name == null) {
throw new NullPointerException("name");
}
final String path = getPropertiesDirPath() + "/" + name + ".properties";
final InputStream in = getInputStream(path);
if (in == null) {
return null;
}
final Properties properties = new Properties();
try {
properties.load(in);
}
finally {
if (in != null) {
try {
in.close();
}
catch (final IOException e) {}
}
}
return properties;
}
public void saveProperties(final String name, final Properties properties) throws IOException {
if (name == null) {
throw new NullPointerException("name");
}
if (properties == null) {
throw new NullPointerException("properties");
}
final String path = getPropertiesDirPath() + "/" + name + ".properties";
final OutputStream out = getOutputStream(path);
try {
properties.store(out, null);
}
finally {
if (out != null) {
try {
out.close();
}
catch (final IOException e) {}
}
}
}
}