How to let the methods of a class only can be invoked by a specialpackage(the class not in the packa

J

Jebel.Star

There is a class A in package XX.ZZ.GG , and A has a static method
A.GetInstance(). There are 3 classes B, C, D in package XX.ZZ .
How can I make the A.GetInstance() only can be invoked by the B, C and
D.
 
P

Patricia Shanahan

There is a class A in package XX.ZZ.GG , and A has a static method
A.GetInstance(). There are 3 classes B, C, D in package XX.ZZ .
How can I make the A.GetInstance() only can be invoked by the B, C and
D.

There are really untidy things you could do at run time to get a stack
trace and check that the caller is one of the specified method.

However, it would be much better to reorganize the packaging.

Patricia
 
J

Jebel.Star

There are really untidy things you could do at run time to get a stack
trace and check that the caller is one of the specified method.

However, it would be much better to reorganize the packaging.

Patricia

Unfortunately I have no right to reorganize the packaging, and I don't
known how to get a stack in the JVM with Ver 1.3 .
 
L

Lew

Roedy said:
There are three levels: public -- everyone, package, just in same
package, and private -- just current class.

And protected - package-private plus inheriting classes. Don't forget.
 
A

Andreas Leitgeb

Unfortunately I have no right to reorganize the packaging, and I don't
known how to get a stack in the JVM with Ver 1.3 .

You could throw an exception, catch it immediately, and see what you
can read from the exception's printStackTrace(), by passing it your
own PrintWriter (or PrintStream), wrapped around some ByteArrayOutputStream.

I just tried it with an (admittedly newer-than-1.3) java:
class X {
public static void main(String[] args) { foo(); }
public static int foo() {
try {
throw new Exception("foo");
} catch (Exception e) {
e.printStackTrace(System.out);
}
return 0;
}
}
Try, if that also works with java-1.3, in that it also
writes the "outer"-levels. To implement this in to-be-
protected code, You'd of course not print to stdout, but
instead to a bytearray.
Happy parsing that automatically. :)

.... But then, again, it's quite an unusual wish, what you made.
 
J

Jebel.Star

Unfortunately I have no right to reorganize the packaging, and I don't
known how to get a stack in the JVM with Ver 1.3 .

You could throw an exception, catch it immediately, and see what you
can read from the exception's printStackTrace(), by passing it your
own PrintWriter (or PrintStream), wrapped around some ByteArrayOutputStream.

I just tried it with an (admittedly newer-than-1.3) java:
class X {
public static void main(String[] args) { foo(); }
public static int foo() {
try {
throw new Exception("foo");
} catch (Exception e) {
e.printStackTrace(System.out);
}
return 0;
}}

Try, if that also works with java-1.3, in that it also
writes the "outer"-levels. To implement this in to-be-
protected code, You'd of course not print to stdout, but
instead to a bytearray.
Happy parsing that automatically. :)

... But then, again, it's quite an unusual wish, what you made.

Thanks for all of you. You let me to find the limitation of my design.
So I change it.

I changed my design:

1 Add a protect method GetInstance() in Class B;
2 Add a class E which is extends from B in package XX.ZZ.GG. Create a
protected method GetInstance() which has the same function of
A.GetInstance() in class E. Remove the Method A.GetInstance().
3 Add a static member 'B e ' withe the default access right in Class
B, construct 'e'in the static block of B as 'E':
static{ e = new E; }

In this design B,C and D can invoke B.e.GetInstance() which is
E.GetInstance(), any other classes that is not in package XX.ZZ (and
also not in package XX.ZZ.GG) can't invoke the E.GetInstance().

Is my design OK ?
 
R

Roedy Green

There is a class A in package XX.ZZ.GG , and A has a static method
A.GetInstance(). There are 3 classes B, C, D in package XX.ZZ .
How can I make the A.GetInstance() only can be invoked by the B, C and
D.

Please follow the caps conventions. See
http://mindprod.com/jgloss/codingconventions.html

Your question translated then becomes:
There is a class A in package xx.zz.gg, and A has a static method
A.getInstance(). There are 3 classes B, C, D in package xx.zz .
How can I make A.getInstance()so that it can only be invoked from
classes B, C and D.

You can't. To do that classes A, B, C and D would have to be in the
same package, and getInstance would need default package scope. You
could still invoke it from class A.

Note that, as far as Java is concerned, package xx.zz.gg and package
xx.zz are TOTALLY unrelated.

see http://mindprod.com/jgloss/package.html
 
J

Jebel

Please follow the caps conventions. Seehttp://mindprod.com/jgloss/codingconventions.html

Your question translated then becomes:


You can't. To do that classes A, B, C and D would have to be in the
same package, and getInstance would need default package scope. You
could still invoke it from class A.

Note that, as far as Java is concerned, package xx.zz.gg and package
xx.zz are TOTALLY unrelated.

seehttp://mindprod.com/jgloss/package.html

I know that "package xx.zz.gg and package xx.zz are TOTALLY unrelated
".The names of the two packages are no meaning for my problem.

The classes A and E are in the package XX.ZZ.GG; and the classes B,
C and D are in the package XX.ZZ.
The class E extends from class B.

When the class C wants to invoke the E.GetInstance()(has the same
function of the previous A.GetInstance) it invokes B.e.GetInstance().

package XX.ZZ;
import XX.ZZ.GG.A;
public class C
{
public void Func()
{
... ...
A a = B.e.GetInstanc();
... ...

}

}


The 'e' is a static member of class B, and 'e' is declared as B but
construct as E:

package XX.ZZ;
import XX.ZZ.GG.E;
import XX.ZZ.GG.A;
public class B
{
static B e;

static{
e = new E;
}
protect A GetInstance(){ return null;}

... ...
}

And the class E and class A are in the same package, E can do some
thing in its method GetInstance with A.
package XX.ZZ.GG;
import XX.ZZ.B;
final public class C extends B
{
private static A onlyOne;
protect A GetInstance()
{
if(onlyOne == NULL){ onlyOne = new A;}
return onlyOne;
}
}

Class A :
package XX.ZZ.GG;
public class A
{
// the access right of constructer of A is
default( the class in the same package can access)
A(){... ...}

... ...
}

That is all.
 
A

Andreas Leitgeb

1 Add a protect method GetInstance() in Class B;
2 Add a class E which is extends from B in package XX.ZZ.GG. Create a
protected method GetInstance() which has the same function of
A.GetInstance() in class E. Remove the Method A.GetInstance().
3 Add a static member 'B e ' withe the default access right in Class
B, construct 'e'in the static block of B as 'E':
static{ e = new E; }

I'm not sure if I remember all involved classes correctly:
xx.zz.gg.B is the one you want only accessible from
classes in package xx.zz, which is principially
not possible to guarantee from JLS point fo view.

So, you create a class
xx.zz.E which derives from B, and thus has also available
all of B's protected functionality.

However, anyone else could create yet another derivative of B,
as hostile.mypackage.MyE, using the same mechanism as your E does,
to still access xx.zz.gg.B
Is my design OK ?
It's quite complicated for hardly any gain.

Java's protection scheme *cannot* discriminate between two
packages, when both are different from the current one.
Whatever you can do from classes of package xx.zz to access
classes in xx.zz.gg, you can always do the same from any
unrelated package aa.bb.cc, as well.

There are exactly these possibilities:
- use reflection or exception-stacktraces at runtime to
determine calling class (quite complicated, if you're
stuck in 1.3, and still some overhead even with 1.4's
new methods for easier stack-inspection.
- put all the relevant classes in one package. Or add a
class C to package xx.zz.gg that will wrap B's methods
such, that no misuse can occur when calling through C.
Then you can give all B's methods default-access.

Maybe we can help more, if you tell us, who/what exactly you
want to protect your class B from.
E.g. against crackers? Against accidental inappropriate use
from other parts of your own project?
 
T

Thomas Schodt

There is a class A in package xx.zz.gg , and A has a static method
A.getInstance(). There are 3 classes B, C, D in package xx.zz
How can I make the A.getInstance() only can be invoked by the B, C and D

class A {
private A() {};
private static final Set allowed = new HashSet() {{
add("xx.zz.B");
add("xx.zz.C");
add("xx.zz.D");
}};
static A a = null;
static A getInstance() {
Class[] ca = new SecurityManager() {
protected Class[] getClassContext() {
return super.getClassContext();
}
}.getClassContext();
// ca[0] is the anonymous security manager
// ca[1] is this class ("A")
// ca[2] is the calling class
if (!allowed.contains(ca[2].getName())) {
throw new InstantiationError("Not allowed from "+ca[2]);
}
if (a==null) { a = new A(); }
return a;
}
}
 
A

Andreas Leitgeb

Andreas Leitgeb said:
There are exactly these possibilities:
- use reflection or exception-stacktraces at runtime to
determine calling class (quite complicated, if you're
stuck in 1.3, and still some overhead even with 1.4's
new methods for easier stack-inspection.

Based on Thomas Schodt's posting, the SecurityManager appears
to make a nicer variant of this strategy, but is still only
doing runtime-checking.
- put all the relevant classes in one package. Or add a
class C to package xx.zz.gg that will wrap B's methods
such, that no misuse can occur when calling through C.
Then you can give all B's methods default-access.

That would allow compiletime checking.
 
L

Lew

Roedy said:

Please note that ignoring good advice, especially from one such as Roedy who
really goes out of his way to be helpful, is risky. You send a message that
you aren't really interested in good advice, thus lowering the expected value
of advice that you will receive. Quoting that advice, then disregarding,
gives the no doubt accidental impression that you are evincing deliberate
disrespect. I'm sure that you did not mean that, of course.

There's good reason for the coding conventions, particular where upper- and
lower-case names are concerned. These conventions facilitate discourse about
Java programs. Discourse about Java programs is the whole point of the
clj.programmer newsgroup. There is a tolerance for variation from some parts
of the convention, formalized in 1999, but only to a point. Indentation, for
example, has two major variants with permissible indentation sizes that can
vary in a narrow range. However, the case conventions are pretty solid and
should not be ignored.

Java from the beginning has been a "literate programming" language -
information about the program is embedded in the source code for the program.
Javadocs are one aspect of that. Annotations are another. The naming
conventions stress the use of names out of the domain of discourse - the
logical model for the program, not out of the implementation. Thus
"WidgetExtractor" tells us by the initial upper-case letter that this is a
class name for something that models a widget extractor. No need to embed the
redundant "Class" in a name like "WidgetExtractorClass". The identifier
"widgetExtractor" in this context now tells us that we see an instance of that
class. "widgetExtractor()" jars the senses, because it's a noun phrase for a
method name; "widgetExtract()" would be more comfortable. With little if any
cognitive strain one can infer many things about the logic and the domain
model from a source code artifact without interrupting the flow of reviewing
it, if these conventions are rigorously followed.

So please, for both engineering and social reasons, use lower-case identifiers
for your package names.
 
J

Jebel

I'm not sure if I remember all involved classes correctly:
xx.zz.gg.B is the one you want only accessible from
classes in package xx.zz, which is principially
not possible to guarantee from JLS point fo view.

So, you create a class
xx.zz.E which derives from B, and thus has also available
all of B's protected functionality.

However, anyone else could create yet another derivative of B,
as hostile.mypackage.MyE, using the same mechanism as your E does,
to still access xx.zz.gg.B


It's quite complicated for hardly any gain.

Java's protection scheme *cannot* discriminate between two
packages, when both are different from the current one.
Whatever you can do from classes of package xx.zz to access
classes in xx.zz.gg, you can always do the same from any
unrelated package aa.bb.cc, as well.

There are exactly these possibilities:
- use reflection or exception-stacktraces at runtime to
determine calling class (quite complicated, if you're
stuck in 1.3, and still some overhead even with 1.4's
new methods for easier stack-inspection.
- put all the relevant classes in one package. Or add a
class C to package xx.zz.gg that will wrap B's methods
such, that no misuse can occur when calling through C.
Then you can give all B's methods default-access.

Maybe we can help more, if you tell us, who/what exactly you
want to protect your class B from.
E.g. against crackers? Against accidental inappropriate use
from other parts of your own project?

There is some thing that I didn't say clearly. I am designing a
platform and use some source(the package xx.zz) of another company, so
I can't move my source(the package xx.zz.gg) into the package xx.zz.
I can prevent the applications that use my source as platform to
create the package xx.zz from the classloader( the applications must
use the classloader that offered from me). And the class B will know
what is the name of my package and class. So I think applications
can't overrides my class E.
I want to prevent that if My design is betrayed, the applications also
can't disturb the behavior of package xx.zz.

And I am not very understand how to do this:
- put all the relevant classes in one package. Or add a
class C to package xx.zz.gg that will wrap B's methods
such, that no misuse can occur when calling through C.
Then you can give all B's methods default-access.


Thank you very much.
Jebel
 
L

Lew

Thomas said:
There is a class A in package xx.zz.gg , and A has a static method
A.getInstance(). There are 3 classes B, C, D in package xx.zz
How can I make the A.getInstance() only can be invoked by the B, C and D

class A {
private A() {};
private static final Set allowed = new HashSet() {{
add("xx.zz.B");
add("xx.zz.C");
add("xx.zz.D");
}};
static A a = null;
static A getInstance() {
Class[] ca = new SecurityManager() {
protected Class[] getClassContext() {
return super.getClassContext();
}
}.getClassContext();
// ca[0] is the anonymous security manager
// ca[1] is this class ("A")
// ca[2] is the calling class
if (!allowed.contains(ca[2].getName())) {
throw new InstantiationError("Not allowed from "+ca[2]);
}
if (a==null) { a = new A(); }
return a;
}
}

That's a great pattern. Take it a step further and store a
Map <String, Class <? extends Allowed>>
or a Map <AllowedEnum, Class <? extends Allowed>>
where 'Allowed' is a supertype for the classes that are allowed. The 'String'
or 'AllowedEnum' enum identify the particular implementing class for each case
you want to permit.

For that matter, you could craft an 'AllowedEnum' where each enum instance's
behavior does what you want - that could well be your optimal solution in that
it gives you compile-time safety on the behaviors, not merely run-time checks.
From a maintenance standpoint, such an enum collects verification of an
action's legality and its activity into a single class, binding them at
compile time, making life easier.

The downside to the enum implementation is that you have to recompile the
world to extend the behaviors. If runtime configurability is what you need,
then you need a runtime technique such as the ServiceProvider pattern.
 
S

Stefan Ram

How can I make the A.GetInstance() only can be invoked by the B

Any static measure is insufficient, because new classes
can be generated and loaded at run-time. Such classes would
not have been inspected by a static measure.

Therefore, the measure must be dynamic. The answers I am aware
of have implied that »A.GetInstance()« will somehow check its
caller. Such answers do not actually address how to /prevent/
the invocation, because at the time when »A.GetInstance()«
checks its caller it already /has been/ invoked, so it is too
late to prevent it. The question was to prevent this, not to
detect and report it, once it has happend.

Therefore, it might not be possible to do this at all.

One could use a patched JVM to do this.

However, there might be multiple »B« classes (one for each
class loader). One also needs to specify which of them should
be allowed to call »A.GetInstance()«. For this, one needs
to identify the class loaders involved.
 
R

Roedy Green

It seems to me you would have to make getClassContext public. Is it
accessible just as protected? The original was already protected.

// Determining the calling class.
// ca[0] is the anonymous security manager
// ca[1] is this class
// ca[2] is the calling class
Class[] ca = new SecurityManager()
{
// convert from protected to public to make the method accessible.
public Class[] getClassContext()
{
return super.getClassContext();
}
}.getClassContext();
 
J

Jebel

Based on Thomas Schodt's posting, the SecurityManager appears
to make a nicer variant of this strategy, but is still only
doing runtime-checking.

I think homas Schodt's design is much better than mine, simple and
effective. But I want to know that if I invoke A.GetInstance() very
frequently, id the SecurityManager .getClassContext() going to take
much time?

-------------------------------------------------------------------------------------------------
That would allow compiletime checking.

I not understand how to do this. How can I "wrap" B's methods ?
Would you please provide some code as a example?

Thanks a lot.
Jebel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top