Why doesn't this Netbeans print from this code in the lower console - netbeans

This code will not produce any text output from the lower output console. Am I missing a configuration setting or is the code wrong?
The code seems to be effective as the console will display that the build was successful in 0 seconds.
public class SpaceRemover {
public static void main(String[] args) {
String mostFamous = "Rudolph the Red-Nosed Reindeer";
char[] mfl = mostFamous.toCharArray();
for (int dex = 0; dex < mfl.length; dex++) {
char current = mfl[dex];
if (current != ' ') {
System.out.print(current);
} else {
System.out.print('.');
}
}
System.out.println();
}
}
Build was successful yet no text was printed.

Related

How to solve NoClassDefFoundError?

I am enrolled in the Duke University course offered by coursera "Java-Programming-Arrays-Lists-and-Structured-data".
I am using Eclipse instead of using BlueJ for my own ease. But when I try to compile the program I get the following error.
Exception in thread "main" java.lang.NoClassDefFoundError: edu/duke/FileResource
I have imported the jar file edu.duke.* and trying to run the program from the main method.
Can someone kindly help how to solve this problem?
import java.lang.*;
import edu.duke.*;
public class WordLengths {
public void countWordLengths (FileResource resource, int[] counts) {
for(String word:resource.words()) {
int wordLength = word.length();
for(int i = 0; i < wordLength; i++) {
char curChar = word.charAt(i);
if((i == 0) || (i == wordLength - 1)) {
if(!Character.isLetter(curChar))
wordLength--;
}
}
counts[wordLength]++;
System.out.println(" Words of length "+ wordLength +" "+ word);
}
}
public void indexOfMax (int[] values) {
int maxIndex = 0;
int position = 0;
for(int i = 0; i < values.length; i++) {
if(values[i] > maxIndex) {
maxIndex = values[i];
position = i;
}
}
System.out.println("The most common word is :"+ position);
}
public void testCountWordLengths () {
FileResource f = new FileResource("C:\\Users\\Ramish-HP\\eclipse-workspace\\Assignment1\\smallHamlet.txt");
int[] counts = new int[31];
countWordLengths(f, counts);
indexOfMax(counts);
}
}
public class WordLengthsTest {
public static void main(String[] args) {
WordLengths wl = new WordLengths();
wl.testCountWordLengths();
}
}
java.lang.NoClassDefFoundError commonly thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
Reference: https://docs.oracle.com/javase/7/docs/api/java/lang/NoClassDefFoundError.html
I will suggest to check run time libraries.

Issue with JFrame, opens blank

For a project of mine (I'm very new & even newer to guis) I'm making a GUI based game it has worked so far however, when you complete level one, it reopens level two but the JFrame is completely white and unresponsive, I have tried a few things but however I am not close to finding out what the issue is. Please help me, The code for the game is:
public class gameWithGuis extends JFrame implements ActionListener, Runnable{
static int levelNum = 1;
static int find;
static int length = 3;
static int area = length * length;
static ArrayList<JButton> buttonsHolder = new ArrayList<JButton>();
Container pane = getContentPane();
static gameWithGuis threadA = new gameWithGuis(); //Starts 10 second timer
static Thread timerThread = new Thread(threadA);
static boolean levelUp = false;
public void run(){
try{
int time = 1;
while (time<=10){
Thread.sleep(1000);
time++;
}
super.dispose();
JOptionPane.showMessageDialog(null,"You have ran out of time! Game over!");
highscores(levelNum);
}catch (Exception e){}
}
public void main(){
Scanner sc = new Scanner(System.in);
JOptionPane.showMessageDialog(null,"Welcome to pseudo-Where's Wally, look for the lower case L(l) character.");
JOptionPane.showMessageDialog(null,"You get 10 seconds to find it.");
JOptionPane.showMessageDialog(null,"The answer are the coordinates multiplied together.");
JOptionPane.showMessageDialog(null,"That is what you must type in. Good luck!");
JOptionPane.showMessageDialog(null,"Ready?..");
char clear = (char)(12);
System.out.print(clear);
timerThread.start();
makingGrid();
}
public static void highscores(int levelNum){
AQAWriteTextFile2013 writer = new AQAWriteTextFile2013();
AQAReadTextFile2013 reader = new AQAReadTextFile2013();
Scanner scTwo = new Scanner(System.in);
String fileName = "highscores.txt";
String save = JOptionPane.showInputDialog(null,"Would you like to save your score? (yes or no): ");
if (save.equalsIgnoreCase("yes")){
String runningLine = "";
String name = JOptionPane.showInputDialog(null,"Name please: ");
writer.openFile(fileName, true); //opens highscore file
String writeLine = name + "\t" + levelNum;
writer.writeToTextFile(writeLine); //writes your name and the level you reached to the file
writer.closeFile();
reader.openTextFile(fileName); //shows you the list of peoples scores
JOptionPane.showMessageDialog(null,"Current Highscores: ");
String line = reader.readLine();
if (line ==null) JOptionPane.showMessageDialog(null,"- - NONE - -"); //if file is empty
do //prints the lines within the file
{
line = reader.readLine();
runningLine = runningLine+"\n"+line+" ";
}while (line !=null);
JOptionPane.showMessageDialog(null,runningLine);
reader.closeFile();
System.exit(0);
} else if (save.equalsIgnoreCase("no")){
JOptionPane.showMessageDialog(null,"Okay, thank you for playing!");
System.exit(0);
} else {
JOptionPane.showMessageDialog(null,"Please answer yes or no."); //validation
}
}
public static void main(String[] args) throws Exception{
new gameWithGuis().main();
}
#Override
public void actionPerformed(ActionEvent arg0){
JButton[] buttons = buttonsHolder.toArray(new JButton[buttonsHolder.size()]);
// for(int i = 0; i<=amountOfButtons; i++){
// buttonsHolder[].toArray();
// // buttons[i] = buttonsHolder[i];
// }
if(arg0.getSource().equals(buttons[find])){
timerThread.stop();
JOptionPane.showMessageDialog(null,"Correct!");
levelNum++;
JOptionPane.showMessageDialog(null,"Level up! You are now on level: "+levelNum+". The grid has an area of "+(length*length)+" now.");
levelUp = true; //go through to the next level
pane.removeAll();
super.dispose();
makingGrid();
}else{
timerThread.stop();
JOptionPane.showMessageDialog(null,"You guessed wrong! Game over!");
JOptionPane.showMessageDialog(null,"You reached level: "+levelNum+".");
highscores(levelNum);
}
}
public void makingGrid(){
do{
if(levelNum>1){
length = length + 2; //increase length and height of box by 2 both ways
area = length*length;
}
JButton[] buttons = new JButton[area];
Random gen = new Random();
find = gen.nextInt(area);
setTitle("Where's J?");
// Container pane = getContentPane();
pane.setLayout(new GridLayout(length, length));
for(int i = 0; i<area; i++){
buttons[i] = new JButton();
buttons[i].setText("I");
if(i == find){
buttons[i].setText("J");
}
buttonsHolder.add(buttons[i]);
pane.add(buttons[i]);
buttons[i].addActionListener(this);
}
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// timerThread.start();
} while (levelUp);
}
}
Please no sarcastic comments if I'm being stupid and missed something obvious too you, I'm new too this language and to this website. Thanks for any help.
don't worry... No one will give you a sarcastic comment. It is just not right or fair.
Your code has a lot to improve. But congratulations for writing it!
Your problem is that levelUp is always true on the second level. This causes an infinite loop inside the makingGrid(). In this case JFrame stop repainting.

Writing the path of a dragdrop file to a textbox

EDIT: The code below is a class I created in order to have a drag/drop richtextbox in which dragging a file into it causes the information inside the file appear in the richtextbox. This works perfectly, I even made it so decimal characters over 128 appear as binary so I can see bitmap images to some degree.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Troy_PCL_Utility
{
public class DragDropRichTextBox : RichTextBox
{
public DragDropRichTextBox()
{
this.AllowDrop = true;
this.DragDrop += DragDropRichTextBox_DragDrop;
}
public static class BinaryFile
{
private static string[] __byteLookup = new string[300];
static BinaryFile()
{
//CHARACTERS: All Control ASCII Characters
for (int i = 0x00; i < 0x1E; i++) { __byteLookup[i] = ((char)i).ToString(); }
// Display printable ASCII characters
for (int i = 0x1E; i < 0x7E; i++) { __byteLookup[i] = ((char)i).ToString(); }
//BITMAPS: Display non-printable ASCII characters
//for (int i = 0; i <= 0x00; i++) { __byteLookup[i] = "\\" + i.ToString(); }
for (int i = 0x7E; i <= 0xFF; i++) { __byteLookup[i] = Convert.ToString(i, 2); } //As Binary
//for (int i = 0x00; i <= 0xFF; i++) { __byteLookup[i] = "\\" + i.ToString(); } //As Characters
}
public static string ReadString(string filename)
{
byte[] fileBytes = System.IO.File.ReadAllBytes(filename);
return String.Join("", (from i in fileBytes select __byteLookup[i]).ToArray());
}
}
public void DragDropRichTextBox_DragDrop(object sender, DragEventArgs e)
{
//string[] fileText = e.Data.GetData(DataFormats.FileDrop) as string[];
string[] fileText = e.Data.GetData(DataFormats.FileDrop) as string[];
if (fileText != null)
{
foreach (string name in fileText)
{
try
{
this.AppendText(BinaryFile.ReadString (name) + "\n -------- End of File -------- \n\n");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
}
However, in addition to dragging and dropping content into this richtextbox, I would also like textbox2 on my main form to populate with the path from which the file came from so if the user is dealing with several files they can double check to see which one they are viewing and from which directory.
So I have this class (DragDropRichTextBox : RichTextBox), and I have this other class (Main Form). I'm not sure how to accomplish this task. Should the code to copy the directory into textbox2 belong in my DragDrop class (above), is that even possible? Or should I create an event from the richtextbox in my main?
I tried clicking on the richtextbox (that derived from my DragDropRichTextBox class) and then created a drag/drop event from where I tried to make it so dragging and dropping copy the file path to textbox2, but I had no luck. Here is the code I tried. I don't feel confident in it:
private void dragDropRichTextBox1_DragDrop(object sender, DragEventArgs e)
{
string fileName = (string) e.Data.GetData(DataFormats.FileDrop, false);
textBox2.Text = fileName;
}
Does anyone have any suggestions for the new guy? Thank you for your help.

What's wrong with this simplest jflex code?

I'm learning jflex, and wrote a simplest jflex code, which makes a single character #:
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
%%
%class PubspecLexer
%implements FlexLexer
%unicode
%type IElementType
%function advance
%debug
Comment = "#"
%%
{Comment} { System.out.println("Found comment!"); return PubTokenTypes.Comment; }
. { return PubTokenTypes.BadCharacter; }
Then I generate a PubspecLexer class, and try it:
public static void main(String[] args) throws IOException {
PubspecLexer lexer = new PubspecLexer(new StringReader("#!!!!!"));
for (int i = 0; i < 3; i++) {
IElementType token = lexer.advance();
System.out.println(token);
}
}
But it prints 3 nulls:
null
null
null
Why it neither return Comment nor BadCharacter?
It's not jflex problem, actually, it's because the idea-flex changes original usage.
When use jflex to write intellij-idea plugins, we are using a patched "JFlex.jar" and "idea-flex.skeleton", later defines the zzRefill method as:
private boolean zzRefill() throws java.io.IOException {
return true;
}
Instead of original:
private boolean zzRefill() throws java.io.IOException {
// ... ignore some code
/* finally: fill the buffer with new input */
int numRead = zzReader.read(zzBuffer, zzEndRead,
zzBuffer.length-zzEndRead);
// ... ignore some code
// numRead < 0
return true;
}
Notice there is a zzReader in the code, and which holds the string #!!!!! I passed in. But in the idea-flex version, which is never used.
So to work with idea-flex version, I should use it like this:
public class MyLexer extends FlexAdapter {
public MyLexer() {
super(new PubspecLexer((Reader) null));
}
}
Then:
public static void main(String[] args) {
String input = "#!!!!!";
MyLexer lexer = new MyLexer();
lexer.start(input);
for (int i = 0; i < 3; i++) {
System.out.println(lexer.getTokenType());
lexer.advance();
}
}
Which prints:
match: --#--
action [19] { System.out.println("Found comment!"); return PubTokenTypes.Comment(); }
Found comment!
Pub:Comment
match: --!--
action [20] { return PubTokenTypes.BadCharacter(); }
Pub:BadCharacter
match: --!--
action [20] { return PubTokenTypes.BadCharacter(); }
Pub:BadCharacter

Can I drag items from Outlook into my SWT application?

Background
Our Eclipse RCP 3.6-based application lets people drag files in for storage/processing. This works fine when the files are dragged from a filesystem, but not when people drag items (messages or attachments) directly from Outlook.
This appears to be because Outlook wants to feed our application the files via a FileGroupDescriptorW and FileContents, but SWT only includes a FileTransfer type. (In a FileTransfer, only the file paths are passed, with the assumption that the receiver can locate and read them. The FileGroupDescriptorW/FileContents approach can supply files directly application-to-application without writing temporary files out to disk.)
We have tried to produce a ByteArrayTransfer subclass that could accept FileGroupDescriptorW and FileContents. Based on some examples on the Web, we were able to receive and parse the FileGroupDescriptorW, which (as the name implies) describes the files available for transfer. (See code sketch below.) But we have been unable to accept the FileContents.
This seems to be because Outlook offers the FileContents data only as TYMED_ISTREAM or TYMED_ISTORAGE, but SWT only understands how to exchange data as TYMED_HGLOBAL. Of those, it appears that TYMED_ISTORAGE would be preferable, since it's not clear how TYMED_ISTREAM could provide access to multiple files' contents.
(We also have some concerns about SWT's desire to pick and convert only a single TransferData type, given that we need to process two, but we think we could probably hack around that in Java somehow: it seems that all the TransferDatas are available at other points of the process.)
Questions
Are we on the right track here? Has anyone managed to accept FileContents in SWT yet? Is there any chance that we could process the TYMED_ISTORAGE data without leaving Java (even if by creating a fragment-based patch to, or a derived version of, SWT), or would we have to build some new native support code too?
Relevant code snippets
Sketch code that extracts file names:
// THIS IS NOT PRODUCTION-QUALITY CODE - FOR ILLUSTRATION ONLY
final Transfer transfer = new ByteArrayTransfer() {
private final String[] typeNames = new String[] { "FileGroupDescriptorW", "FileContents" };
private final int[] typeIds = new int[] { registerType(typeNames[0]), registerType(typeNames[1]) };
#Override
protected String[] getTypeNames() {
return typeNames;
}
#Override
protected int[] getTypeIds() {
return typeIds;
}
#Override
protected Object nativeToJava(TransferData transferData) {
if (!isSupportedType(transferData))
return null;
final byte[] buffer = (byte[]) super.nativeToJava(transferData);
if (buffer == null)
return null;
try {
final DataInputStream in = new DataInputStream(new ByteArrayInputStream(buffer));
long count = 0;
for (int i = 0; i < 4; i++) {
count += in.readUnsignedByte() << i;
}
for (int i = 0; i < count; i++) {
final byte[] filenameBytes = new byte[260 * 2];
in.skipBytes(72); // probable architecture assumption(s) - may be wrong outside standard 32-bit Win XP
in.read(filenameBytes);
final String fileNameIncludingTrailingNulls = new String(filenameBytes, "UTF-16LE");
int stringLength = fileNameIncludingTrailingNulls.indexOf('\0');
if (stringLength == -1)
stringLength = 260;
final String fileName = fileNameIncludingTrailingNulls.substring(0, stringLength);
System.out.println("File " + i + ": " + fileName);
}
in.close();
return buffer;
}
catch (final Exception e) {
return null;
}
}
};
In the debugger, we see that ByteArrayTransfer's isSupportedType() ultimately returns false for the FileContents because the following test is not passed (since its tymed is TYMED_ISTREAM | TYMED_ISTORAGE):
if (format.cfFormat == types[i] &&
(format.dwAspect & COM.DVASPECT_CONTENT) == COM.DVASPECT_CONTENT &&
(format.tymed & COM.TYMED_HGLOBAL) == COM.TYMED_HGLOBAL )
return true;
This excerpt from org.eclipse.swt.internal.ole.win32.COM leaves us feeling less hope for an easy solution:
public static final int TYMED_HGLOBAL = 1;
//public static final int TYMED_ISTORAGE = 8;
//public static final int TYMED_ISTREAM = 4;
Thanks.
even if
//public static final int TYMED_ISTREAM = 4;
Try below code.. it should work
package com.nagarro.jsag.poc.swtdrag;
imports ...
public class MyTransfer extends ByteArrayTransfer {
private static int BYTES_COUNT = 592;
private static int SKIP_BYTES = 72;
private final String[] typeNames = new String[] { "FileGroupDescriptorW", "FileContents" };
private final int[] typeIds = new int[] { registerType(typeNames[0]), registerType(typeNames[1]) };
#Override
protected String[] getTypeNames() {
return typeNames;
}
#Override
protected int[] getTypeIds() {
return typeIds;
}
#Override
protected Object nativeToJava(TransferData transferData) {
String[] result = null;
if (!isSupportedType(transferData) || transferData.pIDataObject == 0)
return null;
IDataObject data = new IDataObject(transferData.pIDataObject);
data.AddRef();
// Check for descriptor format type
try {
FORMATETC formatetcFD = transferData.formatetc;
STGMEDIUM stgmediumFD = new STGMEDIUM();
stgmediumFD.tymed = COM.TYMED_HGLOBAL;
transferData.result = data.GetData(formatetcFD, stgmediumFD);
if (transferData.result == COM.S_OK) {
// Check for contents format type
long hMem = stgmediumFD.unionField;
long fileDiscriptorPtr = OS.GlobalLock(hMem);
int[] fileCount = new int[1];
try {
OS.MoveMemory(fileCount, fileDiscriptorPtr, 4);
fileDiscriptorPtr += 4;
result = new String[fileCount[0]];
for (int i = 0; i < fileCount[0]; i++) {
String fileName = handleFile(fileDiscriptorPtr, data);
System.out.println("FileName : = " + fileName);
result[i] = fileName;
fileDiscriptorPtr += BYTES_COUNT;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
OS.GlobalFree(hMem);
}
}
} finally {
data.Release();
}
return result;
}
private String handleFile(long fileDiscriptorPtr, IDataObject data) throws Exception {
// GetFileName
char[] fileNameChars = new char[OS.MAX_PATH];
byte[] fileNameBytes = new byte[OS.MAX_PATH];
COM.MoveMemory(fileNameBytes, fileDiscriptorPtr, BYTES_COUNT);
// Skip some bytes.
fileNameBytes = Arrays.copyOfRange(fileNameBytes, SKIP_BYTES, fileNameBytes.length);
String fileNameIncludingTrailingNulls = new String(fileNameBytes, "UTF-16LE");
fileNameChars = fileNameIncludingTrailingNulls.toCharArray();
StringBuilder builder = new StringBuilder(OS.MAX_PATH);
for (int i = 0; fileNameChars[i] != 0 && i < fileNameChars.length; i++) {
builder.append(fileNameChars[i]);
}
String name = builder.toString();
try {
File file = saveFileContent(name, data);
if (file != null) {
System.out.println("File Saved # " + file.getAbsolutePath());
;
}
} catch (IOException e) {
System.out.println("Count not save file content");
;
}
return name;
}
private File saveFileContent(String fileName, IDataObject data) throws IOException {
File file = null;
FORMATETC formatetc = new FORMATETC();
formatetc.cfFormat = typeIds[1];
formatetc.dwAspect = COM.DVASPECT_CONTENT;
formatetc.lindex = 0;
formatetc.tymed = 4; // content.
STGMEDIUM stgmedium = new STGMEDIUM();
stgmedium.tymed = 4;
if (data.GetData(formatetc, stgmedium) == COM.S_OK) {
file = new File(fileName);
IStream iStream = new IStream(stgmedium.unionField);
iStream.AddRef();
try (FileOutputStream outputStream = new FileOutputStream(file)) {
int increment = 1024 * 4;
long pv = COM.CoTaskMemAlloc(increment);
int[] pcbWritten = new int[1];
while (iStream.Read(pv, increment, pcbWritten) == COM.S_OK && pcbWritten[0] > 0) {
byte[] buffer = new byte[pcbWritten[0]];
OS.MoveMemory(buffer, pv, pcbWritten[0]);
outputStream.write(buffer);
}
COM.CoTaskMemFree(pv);
} finally {
iStream.Release();
}
return file;
} else {
return null;
}
}
}
Have you looked at https://bugs.eclipse.org/bugs/show_bug.cgi?id=132514 ?
Attached to this bugzilla entry is an patch (against an rather old version of SWT) that might be of interest.
I had the same problem and created a small library providing a Drag'n Drop Transfer Class for JAVA SWT. It can be found here:
https://github.com/HendrikHoetker/OutlookItemTransfer
Currently it supports dropping Mail Items from Outlook to your Java SWT application and will provide a list of OutlookItems with the Filename and a byte array of the file contents.
All is pure Java and in-memory (no temp files).
Usage in your SWT java application:
if (OutlookItemTransfer.getInstance().isSupportedType(event.currentDataType)) {
Object o = OutlookItemTransfer.getInstance().nativeToJava(event.currentDataType);
if (o != null && o instanceof OutlookMessage[]) {
OutlookMessage[] outlookMessages = (OutlookMessage[])o;
for (OutlookMessage msg: outlookMessages) {
//...
}
}
}
The OutlookItem will then provide two elements: filename as String and file contents as array of byte.
From here on, one could write it to a file or further process the byte array.
To your question above:
- What you find in the file descriptor is the filename of the outlook item and a pointer to an IDataObject
- the IDataObject can be parsed and will provide an IStorage object
- The IStorageObject will be then a root container providing further sub-IStorageObjects or IStreams similar to a filesystem (directory = IStorage, file = IStream
You find those elements in the following lines of code:
Get File Contents, see OutlookItemTransfer.java, method nativeToJava:
FORMATETC format = new FORMATETC();
format.cfFormat = getTypeIds()[1];
format.dwAspect = COM.DVASPECT_CONTENT;
format.lindex = <fileIndex>;
format.ptd = 0;
format.tymed = TYMED_ISTORAGE | TYMED_ISTREAM | COM.TYMED_HGLOBAL;
STGMEDIUM medium = new STGMEDIUM();
if (data.GetData(format, medium) == COM.S_OK) {
// medium.tymed will now contain TYMED_ISTORAGE
// in medium.unionfield you will find the root IStorage
}
Read the root IStorage, see CompoundStorage, method readOutlookStorage:
// open IStorage object
IStorage storage = new IStorage(pIStorage);
storage.AddRef();
// walk through the content of the IStorage object
long[] pEnumStorage = new long[1];
if (storage.EnumElements(0, 0, 0, pEnumStorage) == COM.S_OK) {
// get storage iterator
IEnumSTATSTG enumStorage = new IEnumSTATSTG(pEnumStorage[0]);
enumStorage.AddRef();
enumStorage.Reset();
// prepare statstg structure which tells about the object found by the iterator
long pSTATSTG = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, STATSTG.sizeof);
int[] fetched = new int[1];
while (enumStorage.Next(1, pSTATSTG, fetched) == COM.S_OK && fetched[0] == 1) {
// get the description of the the object found
STATSTG statstg = new STATSTG();
COM.MoveMemory(statstg, pSTATSTG, STATSTG.sizeof);
// get the name of the object found
String name = readPWCSName(statstg);
// depending on type of object
switch (statstg.type) {
case COM.STGTY_STREAM: { // load an IStream (=File)
long[] pIStream = new long[1];
// get the pointer to the IStream
if (storage.OpenStream(name, 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, pIStream) == COM.S_OK) {
// load the IStream
}
}
case COM.STGTY_STORAGE: { // load an IStorage (=SubDirectory) - requires recursion to traverse the sub dies
}
}
}
}
// close the iterator
enumStorage.Release();
}
// close the IStorage object
storage.Release();