blob: 3a8e5144c48d4e125c5059c659e696540240f95e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.security.storage;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import org.eclipse.equinox.internal.security.auth.AuthPlugin;
import org.eclipse.equinox.internal.security.auth.nls.SecAuthMessages;
import org.eclipse.osgi.util.NLS;
/**
* PLEASE READ BEFORE CHANGING THIS FILE
*
* At present most of the methods expect only file URLs. The API methods
* take URLs for possible future expansion, and there is some code below
* that would work with some other URL types, but the only supported URL
* types at this time are file URLs. Also note that URL paths should not
* be encoded (spaces should be spaces, not "%x20").
*
* On encoding: Java documentation recommends using File.toURI().toURL().
* However, in this process non-alphanumeric characters (including spaces)
* get encoded and can not be used with the rest of Eclipse methods that
* expect non-encoded strings.
*/
public class StorageUtils {
/**
* Characters encoding used by the secure storage.
*/
final public static String CHAR_ENCODING = "UTF-8"; //$NON-NLS-1$
/**
* Default name of the storage file
*/
final private static String propertiesFileName = ".eclipse/org.eclipse.equinox.security/secure_storage"; //$NON-NLS-1$
static private boolean firstCharsetException = true;
/**
* Default locations:
* 1) user.home
* 2) Eclipse config location
*/
static public URL getDefaultLocation() throws IOException {
String userHome = System.getProperty("user.home"); //$NON-NLS-1$
if (userHome != null) {
File file = new File(userHome, propertiesFileName);
// NOTE: Don't use File.toURI().toURL() as it will escape space characters and such.
// The escaped sequence will fail later when we try to open a stream on it.
return file.toURL();
}
// use install location
URL installLocation = AuthPlugin.getDefault().getConfigURL();
if (installLocation != null && isFile(installLocation)) {
File file = new File(installLocation.getPath(), propertiesFileName);
// NOTE: Same thing about toURI() as above
return file.toURL();
}
// practically, we never should reach this point but just in case:
throw new IOException(SecAuthMessages.loginNoDefaultLocation);
}
static public OutputStream getOutputStream(URL url) throws IOException {
if (isFile(url)) {
File file = new File(url.getPath());
if (!file.exists()) {
File parent = file.getParentFile();
if (parent != null && !parent.exists())
parent.mkdirs();
}
return new FileOutputStream(file);
}
// note that code below does not work for File URLs - "by design" Java
// does not support creating output streams on file URLs. Code below should work
// for HTTP URLs; no idea as to the other types of URLs
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
return connection.getOutputStream();
}
static public InputStream getInputStream(URL url) throws IOException {
if (url == null)
return null;
try {
return url.openStream();
} catch (FileNotFoundException e) {
return null; // this is all right, means new file
}
}
static public boolean delete(URL url) {
if (isFile(url)) {
File file = new File(url.getPath());
return file.delete();
}
return false;
}
static public boolean exists(URL url) {
if (isFile(url)) {
File file = new File(url.getPath());
return file.exists();
}
return true;
}
static public boolean isFile(URL url) {
return ("file".equals(url.getProtocol())); //$NON-NLS-1$
}
/**
* The {@link String#getBytes()} truncates non-ASCII chars. As a result
* new String(string.getBytes()) is not the same as the original string. Moreover,
* the default Java encoding can be changed via system variables or startup conditions.
*/
static public byte[] getBytes(String string) {
if (string == null)
return null;
try {
return string.getBytes(CHAR_ENCODING);
} catch (UnsupportedEncodingException e) {
if (firstCharsetException) { // log error once per session
String msg = NLS.bind(SecAuthMessages.unsupoprtedCharEncoding, StorageUtils.CHAR_ENCODING);
AuthPlugin.getDefault().logMessage(msg);
firstCharsetException = false;
}
return string.getBytes();
}
}
/**
* The new String(byte[]) method uses default system encoding which
* might not properly process non-ASCII characters.
*
* Pairing {@link #getBytes(String)} and {@link #getString(byte[])} methods allows round trip
* of non-ASCII characters.
*/
static public String getString(byte[] bytes) {
if (bytes == null)
return null;
try {
return new String(bytes, CHAR_ENCODING);
} catch (UnsupportedEncodingException e) {
if (firstCharsetException) { // log error once per session
String msg = NLS.bind(SecAuthMessages.unsupoprtedCharEncoding, StorageUtils.CHAR_ENCODING);
AuthPlugin.getDefault().logMessage(msg);
firstCharsetException = false;
}
return new String(bytes);
}
}
}